1# Copyright (c) 2012 - 2016 EMC Corporation, Inc.
2# All Rights Reserved.
3#
4#    Licensed under the Apache License, Version 2.0 (the "License"); you may
5#    not use this file except in compliance with the License. You may obtain
6#    a copy of the License at
7#
8#         http://www.apache.org/licenses/LICENSE-2.0
9#
10#    Unless required by applicable law or agreed to in writing, software
11#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13#    License for the specific language governing permissions and limitations
14#    under the License.
15
16import mock
17
18from cinder import context
19from cinder.objects import fields
20from cinder import test
21from cinder.tests.unit import fake_constants as fake
22from cinder.volume.drivers.coprhd import common as coprhd_common
23from cinder.volume.drivers.coprhd import fc as coprhd_fc
24from cinder.volume.drivers.coprhd import iscsi as coprhd_iscsi
25from cinder.volume.drivers.coprhd import scaleio as coprhd_scaleio
26from cinder.volume import volume_types
27
28"""
29Test Data required for mocking
30"""
31export_group_details_data = {
32    "inactive": False,
33    "initiators": [{"creation_time": 1392194176020,
34                    "host": {"id": "urn:storageos:Host:3e21edff-8662-4e60-ab5",
35                             "link": {"href": "/compute/hosts/urn:storageos:H",
36                                      "rel": "self"}},
37                    "hostname": "lglw7134",
38                    "id": "urn:storageos:Initiator:13945431-06b7-44a0-838c-50",
39                    "inactive": False,
40                    "initiator_node": "20:00:00:90:FA:13:81:8D",
41                    "initiator_port": "iqn.1993-08.org.deb:01:222",
42                    "link": {"href": "/compute/initiators/urn:storageos:Initi",
43                             "rel": "self"},
44                    "protocol": "iSCSI",
45                    "registration_status": "REGISTERED",
46                    "tags": []}],
47    "name": "ccgroup",
48    "project": 'project',
49    "tags": [],
50    "tenant": 'tenant',
51    "type": "Host",
52    "varray": {"id": "urn:storageos:VirtualArray:5af376e9-ce2f-493d-9079-a872",
53               "link": {"href": "/vdc/varrays/urn:storageos:VirtualArray:5af3",
54                        "rel": "self"}
55               },
56    "volumes": [{"id": "urn:storageos:Volume:6dc64865-bb25-431c-b321-ac268f16"
57                 "a7ae:vdc1",
58                 "lun": 1
59                 }]
60}
61
62varray_detail_data = {"name": "varray"}
63
64export_group_list = ["urn:storageos:ExportGroup:2dbce233-7da0-47cb-8ff3-68f48"]
65
66iscsi_itl_list = {"itl": [{"hlu": 3,
67                           "initiator": {"id": "urn:storageos:Initiator:13945",
68                                         "link": {"rel": "self",
69                                                  "href": "/comput"},
70                                         "port": "iqn.1993-08.org.deb:01:222"},
71                           "export": {"id": "urn:storageos:ExportGroup:2dbce2",
72                                      "name": "ccgroup",
73                                      "link": {"rel": "self",
74                                               "href": "/block/expo"}},
75                           "device": {"id": "urn:storageos:Volume:aa1fc84a-af",
76                                      "link": {"rel": "self",
77                                               "href": "/block/volumes/urn:s"},
78                                      "wwn": "600009700001957015735330303535"},
79                           "target": {"id": "urn:storageos:StoragePort:d7e42",
80                                      "link": {"rel": "self",
81                                               "href": "/vdc/stor:"},
82                                      "port": "50:00:09:73:00:18:95:19",
83                                      'ip_address': "10.10.10.10",
84                                      'tcp_port': '22'}},
85                          {"hlu": 3,
86                           "initiator": {"id": "urn:storageos:Initiator:13945",
87                                         "link": {"rel": "self",
88                                                  "href": "/comput"},
89                                         "port": "iqn.1993-08.org.deb:01:222"},
90                           "export": {"id": "urn:storageos:ExportGroup:2dbce2",
91                                      "name": "ccgroup",
92                                      "link": {"rel": "self",
93                                               "href": "/block/expo"}},
94                           "device": {"id": "urn:storageos:Volume:aa1fc84a-af",
95                                      "link": {"rel": "self",
96                                               "href": "/block/volumes/urn:s"},
97                                      "wwn": "600009700001957015735330303535"},
98                           "target": {"id": "urn:storageos:StoragePort:d7e42",
99                                      "link": {"rel": "self",
100                                               "href": "/vdc/stor:"},
101                                      "port": "50:00:09:73:00:18:95:19",
102                                      'ip_address': "10.10.10.10",
103                                      'tcp_port': '22'}}]}
104
105fcitl_itl_list = {"itl": [{"hlu": 3,
106                           "initiator": {"id": "urn:storageos:Initiator:13945",
107                                         "link": {"rel": "self",
108                                                  "href": "/comput"},
109                                         "port": "12:34:56:78:90:12:34:56"},
110                           "export": {"id": "urn:storageos:ExportGroup:2dbce2",
111                                      "name": "ccgroup",
112                                      "link": {"rel": "self",
113                                               "href": "/block/expo"}},
114                           "device": {"id": "urn:storageos:Volume:aa1fc84a-af",
115                                      "link": {"rel": "self",
116                                               "href": "/block/volumes/urn:s"},
117                                      "wwn": "600009700001957015735330303535"},
118                           "target": {"id": "urn:storageos:StoragePort:d7e42",
119                                      "link": {"rel": "self",
120                                               "href": "/vdc/stor:"},
121                                      "port": "12:34:56:78:90:12:34:56",
122                                      'ip_address': "10.10.10.10",
123                                      'tcp_port': '22'}},
124                          {"hlu": 3,
125                           "initiator": {"id": "urn:storageos:Initiator:13945",
126                                         "link": {"rel": "self",
127                                                  "href": "/comput"},
128                                         "port": "12:34:56:78:90:12:34:56"},
129                           "export": {"id": "urn:storageos:ExportGroup:2dbce2",
130                                      "name": "ccgroup",
131                                      "link": {"rel": "self",
132                                               "href": "/block/expo"}},
133                           "device": {"id": "urn:storageos:Volume:aa1fc84a-af",
134                                      "link": {"rel": "self",
135                                               "href": "/block/volumes/urn:s"},
136                                      "wwn": "600009700001957015735330303535"},
137                           "target": {"id": "urn:storageos:StoragePort:d7e42",
138                                      "link": {"rel": "self",
139                                               "href": "/vdc/stor:"},
140                                      "port": "12:34:56:78:90:12:34:56",
141                                      'ip_address': "10.10.10.10",
142                                      'tcp_port': '22'}}]}
143
144scaleio_itl_list = {"itl": [{"hlu": -1,
145                             "initiator": {"id":
146                                           "urn:storageos:Initiator:920aee",
147                                           "link": {"rel": "self",
148                                                    "href":
149                                                    "/compute/initiators"},
150                                           "port": "bfdf432500000004"},
151                             "export": {"id":
152                                        "urn:storageos:ExportGroup:5449235",
153                                        "name": "10.108.225.109",
154                                        "link": {"rel": "self",
155                                                 "href":
156                                                 "/block/exports/urn:stor"}},
157                             "device": {"id":
158                                        "urn:storageos:Volume:b3624a83-3eb",
159                                        "link": {"rel": "self",
160                                                 "href": "/block/volume"},
161                                        "wwn":
162                                        "4F48CC4C27A43248092128B400000004"},
163                             "target": {}},
164                            {"hlu": -1,
165                             "initiator": {"id":
166                                           "urn:storageos:Initiator:920aee",
167                                           "link": {"rel": "self",
168                                                    "href":
169                                                    "/compute/initiators/"},
170                                           "port": "bfdf432500000004"},
171                             "export": {"id":
172                                        "urn:storageos:ExportGroup:5449235",
173                                        "name": "10.108.225.109",
174                                        "link": {"rel": "self",
175                                                 "href":
176                                                 "/block/exports/urn:stor"}},
177                             "device": {"id":
178                                        "urn:storageos:Volume:c014e96a-557",
179                                        "link": {"rel": "self",
180                                                 "href":
181                                                 "/block/volumes/urn:stor"},
182                                        "wwn":
183                                        "4F48CC4C27A43248092129320000000E"},
184                             "target": {}}]}
185
186
187class test_volume_data(object):
188    name = 'test-vol1'
189    size = 1
190    volume_name = 'test-vol1'
191    id = fake.VOLUME_ID
192    group_id = None
193    provider_auth = None
194    project_id = fake.PROJECT_ID
195    display_name = 'test-vol1'
196    display_description = 'test volume',
197    volume_type_id = None
198    provider_id = fake.PROVIDER_ID
199
200    def __init__(self, volume_type_id):
201        self.volume_type_id = volume_type_id
202
203
204class source_test_volume_data(object):
205    name = 'source_test-vol1'
206    size = 1
207    volume_name = 'source_test-vol1'
208    id = fake.VOLUME2_ID
209    group_id = None
210    provider_auth = None
211    project_id = fake.PROJECT_ID
212    display_name = 'source_test-vol1'
213    display_description = 'test volume'
214    volume_type_id = None
215
216    def __init__(self, volume_type_id):
217        self.volume_type_id = volume_type_id
218
219
220class test_clone_volume_data(object):
221    name = 'clone-test-vol1'
222    size = 1
223    volume_name = 'clone-test-vol1'
224    id = fake.VOLUME3_ID
225    provider_auth = None
226    project_id = fake.PROJECT_ID
227    display_name = 'clone-test-vol1'
228    display_description = 'clone test volume'
229    volume_type_id = None
230
231    def __init__(self, volume_type_id):
232        self.volume_type_id = volume_type_id
233
234
235class test_snapshot_data(object):
236    name = 'snapshot1'
237    display_name = 'snapshot1'
238    size = 1
239    id = fake.SNAPSHOT_ID
240    volume_name = 'test-vol1'
241    volume_id = fake.VOLUME_ID
242    volume = None
243    volume_size = 1
244    project_id = fake.PROJECT_ID
245    status = fields.SnapshotStatus.AVAILABLE
246
247    def __init__(self, src_volume):
248        self.volume = src_volume
249
250
251def get_connector_data():
252    connector = {'ip': '10.0.0.2',
253                 'initiator': 'iqn.1993-08.org.deb:01:222',
254                 'wwpns': ["1234567890123456", "1234567890543211"],
255                 'wwnns': ["223456789012345", "223456789054321"],
256                 'host': 'fakehost'}
257    return connector
258
259
260class test_group_data(object):
261    name = 'group_name'
262    display_name = 'group_name'
263    id = fake.GROUP_ID
264    volume_type_ids = None
265    volume_types = None
266    group_type_id = None
267    status = fields.GroupStatus.AVAILABLE
268
269    def __init__(self, volume_types, group_type_id):
270        self.group_type_id = group_type_id
271        self.volume_types = volume_types
272
273
274class test_group_type_data(object):
275    name = 'group_name'
276    display_name = 'group_name'
277    groupsnapshot_id = None
278    id = fake.GROUP_TYPE_ID
279    description = 'group'
280
281
282class test_group_snap_data(object):
283    name = 'cg_snap_name'
284    display_name = 'cg_snap_name'
285    id = fake.GROUP_SNAPSHOT_ID
286    group_id = fake.GROUP_ID
287    status = fields.GroupStatus.AVAILABLE
288    snapshots = []
289    group = None
290    group_type_id = None
291
292    def __init__(self, volume_types, group_type_id):
293        self.group_type_id = group_type_id
294        self.group = test_group_data(volume_types, group_type_id)
295
296
297class MockedEMCCoprHDDriverCommon(coprhd_common.EMCCoprHDDriverCommon):
298
299    def __init__(self, protocol, default_backend_name,
300                 configuration=None):
301
302        super(MockedEMCCoprHDDriverCommon, self).__init__(
303            protocol, default_backend_name, configuration)
304
305    def authenticate_user(self):
306        pass
307
308    def get_exports_count_by_initiators(self, initiator_ports):
309        return 0
310
311    def _get_coprhd_volume_name(self, vol, verbose=False):
312        if verbose is True:
313            return {'volume_name': "coprhd_vol_name",
314                    'volume_uri': "coprhd_vol_uri"}
315        else:
316            return "coprhd_vol_name"
317
318    def _get_coprhd_snapshot_name(self, snapshot, resUri):
319        return "coprhd_snapshot_name"
320
321    def _get_coprhd_cgid(self, cgid):
322        return "cg_uri"
323
324    def init_volume_api(self):
325        self.volume_api = mock.Mock()
326        self.volume_api.get.return_value = {
327            'name': 'source_test-vol1',
328            'size': 1,
329            'volume_name': 'source_test-vol1',
330            'id': fake.VOLUME_ID,
331            'group_id': fake.GROUP_ID,
332            'provider_auth': None,
333            'project_id': fake.PROJECT_ID,
334            'display_name': 'source_test-vol1',
335            'display_description': 'test volume',
336            'volume_type_id': fake.VOLUME_TYPE_ID}
337
338    def init_coprhd_api_components(self):
339        self.volume_obj = mock.Mock()
340        self.volume_obj.create.return_value = "volume_created"
341        self.volume_obj.volume_query.return_value = "volume_uri"
342        self.volume_obj.get_storageAttributes.return_value = (
343            'block', 'volume_name')
344        self.volume_obj.storage_resource_query.return_value = "volume_uri"
345        self.volume_obj.is_volume_detachable.return_value = False
346        self.volume_obj.volume_clone_detach.return_value = 'detached'
347        self.volume_obj.getTags.return_value = (
348            ["Openstack-vol", "Openstack-vol1"])
349        self.volume_obj.tag.return_value = "tagged"
350        self.volume_obj.clone.return_value = "volume-cloned"
351
352        if(self.protocol == "iSCSI"):
353            self.volume_obj.get_exports_by_uri.return_value = (
354                iscsi_itl_list)
355        elif(self.protocol == "FC"):
356            self.volume_obj.get_exports_by_uri.return_value = (
357                fcitl_itl_list)
358        else:
359            self.volume_obj.get_exports_by_uri.return_value = (
360                scaleio_itl_list)
361
362        self.volume_obj.list_volumes.return_value = []
363        self.volume_obj.show.return_value = {"id": "vol_id"}
364        self.volume_obj.expand.return_value = "expanded"
365
366        self.tag_obj = mock.Mock()
367        self.tag_obj.list_tags.return_value = [
368            "Openstack-vol", "Openstack-vol1"]
369        self.tag_obj.tag_resource.return_value = "Tagged"
370
371        self.exportgroup_obj = mock.Mock()
372        self.exportgroup_obj.exportgroup_list.return_value = (
373            export_group_list)
374        self.exportgroup_obj.exportgroup_show.return_value = (
375            export_group_details_data)
376
377        self.exportgroup_obj.exportgroup_add_volumes.return_value = (
378            "volume-added")
379
380        self.host_obj = mock.Mock()
381        self.host_obj.list_by_tenant.return_value = []
382        self.host_obj.list_all.return_value = [{'id': "host1_id",
383                                                'name': "host1"}]
384        self.host_obj.list_initiators.return_value = [
385            {'name': "12:34:56:78:90:12:34:56"},
386            {'name': "12:34:56:78:90:54:32:11"},
387            {'name': "bfdf432500000004"}]
388
389        self.hostinitiator_obj = mock.Mock()
390        self.varray_obj = mock.Mock()
391        self.varray_obj.varray_show.return_value = varray_detail_data
392
393        self.snapshot_obj = mock.Mock()
394        mocked_snap_obj = self.snapshot_obj.return_value
395        mocked_snap_obj.storageResource_query.return_value = (
396            "resourceUri")
397        mocked_snap_obj.snapshot_create.return_value = (
398            "snapshot_created")
399        mocked_snap_obj.snapshot_query.return_value = "snapshot_uri"
400
401        self.consistencygroup_obj = mock.Mock()
402        mocked_group_object = self.consistencygroup_obj.return_value
403        mocked_group_object.create.return_value = "CG-Created"
404        mocked_group_object.consistencygroup_query.return_value = "CG-uri"
405
406
407class EMCCoprHDISCSIDriverTest(test.TestCase):
408
409    def setUp(self):
410        super(EMCCoprHDISCSIDriverTest, self).setUp()
411        self.create_coprhd_setup()
412
413    def create_coprhd_setup(self):
414
415        self.configuration = mock.Mock()
416        self.configuration.coprhd_hostname = "10.10.10.10"
417        self.configuration.coprhd_port = "4443"
418        self.configuration.volume_backend_name = "EMCCoprHDISCSIDriver"
419        self.configuration.coprhd_username = "user-name"
420        self.configuration.coprhd_password = "password"
421        self.configuration.coprhd_tenant = "tenant"
422        self.configuration.coprhd_project = "project"
423        self.configuration.coprhd_varray = "varray"
424        self.configuration.coprhd_emulate_snapshot = False
425
426        self.volume_type = self.create_coprhd_volume_type()
427        self.volume_type_id = self.volume_type.id
428        self.group_type = test_group_type_data()
429        self.group_type_id = self.group_type.id
430
431        self.mock_object(coprhd_iscsi.EMCCoprHDISCSIDriver,
432                         '_get_common_driver',
433                         self._get_mocked_common_driver)
434        self.driver = coprhd_iscsi.EMCCoprHDISCSIDriver(
435            configuration=self.configuration)
436
437    def tearDown(self):
438        self._cleanUp()
439        super(EMCCoprHDISCSIDriverTest, self).tearDown()
440
441    def _cleanUp(self):
442        self.delete_vipr_volume_type()
443
444    def create_coprhd_volume_type(self):
445        ctx = context.get_admin_context()
446        vipr_volume_type = volume_types.create(ctx,
447                                               "coprhd-volume-type",
448                                               {'CoprHD:VPOOL':
449                                                'vpool_coprhd'})
450        return vipr_volume_type
451
452    def _get_mocked_common_driver(self):
453        return MockedEMCCoprHDDriverCommon(
454            protocol="iSCSI",
455            default_backend_name="EMCViPRISCSIDriver",
456            configuration=self.configuration)
457
458    def delete_vipr_volume_type(self):
459        ctx = context.get_admin_context()
460        volume_types.destroy(ctx, self.volume_type_id)
461
462    def test_create_destroy(self):
463        volume = test_volume_data(self.volume_type_id)
464
465        self.driver.create_volume(volume)
466        self.driver.delete_volume(volume)
467
468    def test_get_volume_stats(self):
469        vol_stats = self.driver.get_volume_stats(True)
470        self.assertEqual('unknown', vol_stats['free_capacity_gb'])
471
472    def test_create_volume_clone(self):
473        src_volume_data = test_volume_data(self.volume_type_id)
474        clone_volume_data = test_clone_volume_data(self.volume_type_id)
475        self.driver.create_volume(src_volume_data)
476        self.driver.create_cloned_volume(clone_volume_data, src_volume_data)
477        self.driver.delete_volume(src_volume_data)
478        self.driver.delete_volume(clone_volume_data)
479
480    def test_create_destroy_snapshot(self):
481        volume_data = test_volume_data(self.volume_type_id)
482        snapshot_data = test_snapshot_data(
483            source_test_volume_data(self.volume_type_id))
484
485        self.driver.create_volume(volume_data)
486        self.driver.create_snapshot(snapshot_data)
487        self.driver.delete_snapshot(snapshot_data)
488        self.driver.delete_volume(volume_data)
489
490    def test_create_volume_from_snapshot(self):
491
492        src_vol_data = source_test_volume_data(self.volume_type_id)
493        self.driver.create_volume(src_vol_data)
494
495        volume_data = test_volume_data(self.volume_type_id)
496        snapshot_data = test_snapshot_data(src_vol_data)
497
498        self.driver.create_snapshot(snapshot_data)
499        self.driver.create_volume_from_snapshot(volume_data, snapshot_data)
500
501        self.driver.delete_snapshot(snapshot_data)
502        self.driver.delete_volume(src_vol_data)
503        self.driver.delete_volume(volume_data)
504
505    def test_extend_volume(self):
506        volume_data = test_volume_data(self.volume_type_id)
507        self.driver.create_volume(volume_data)
508        self.driver.extend_volume(volume_data, 2)
509        self.driver.delete_volume(volume_data)
510
511    def test_initialize_and_terminate_connection(self):
512        connector_data = get_connector_data()
513        volume_data = test_volume_data(self.volume_type_id)
514
515        self.driver.create_volume(volume_data)
516        res_initialize = self.driver.initialize_connection(
517            volume_data, connector_data)
518        expected_initialize = {'driver_volume_type': 'iscsi',
519                               'data': {'target_lun': 3,
520                                        'target_portal': '10.10.10.10:22',
521                                        'target_iqn':
522                                        '50:00:09:73:00:18:95:19',
523                                        'target_discovered': False,
524                                        'volume_id': fake.VOLUME_ID}}
525        self.assertEqual(
526            expected_initialize, res_initialize, 'Unexpected return data')
527
528        self.driver.terminate_connection(volume_data, connector_data)
529        self.driver.delete_volume(volume_data)
530
531    @mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
532    def test_create_delete_empty_group(self, cg_ss_enabled):
533        cg_ss_enabled.side_effect = [True, True]
534        group_data = test_group_data([self.volume_type],
535                                     self.group_type_id)
536        ctx = context.get_admin_context()
537        self.driver.create_group(ctx, group_data)
538        model_update, volumes_model_update = (
539            self.driver.delete_group(ctx, group_data, []))
540        self.assertEqual([], volumes_model_update, 'Unexpected return data')
541
542    @mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
543    def test_create_update_delete_group(self, cg_ss_enabled):
544        cg_ss_enabled.side_effect = [True, True, True, True]
545        group_data = test_group_data([self.volume_type],
546                                     self.group_type_id)
547        ctx = context.get_admin_context()
548        self.driver.create_group(ctx, group_data)
549
550        volume = test_volume_data(self.volume_type_id)
551        self.driver.create_volume(volume)
552
553        model_update, ret1, ret2 = (
554            self.driver.update_group(ctx, group_data, [volume], []))
555
556        self.assertEqual({'status': fields.GroupStatus.AVAILABLE},
557                         model_update)
558
559        model_update, volumes_model_update = (
560            self.driver.delete_group(ctx, group_data, [volume]))
561        self.assertEqual({'status': fields.GroupStatus.AVAILABLE},
562                         model_update)
563        self.assertEqual([{'status': 'deleted', 'id': fake.VOLUME_ID}],
564                         volumes_model_update)
565
566    @mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
567    def test_create_delete_group_snap(self, cg_ss_enabled):
568        cg_ss_enabled.side_effect = [True, True]
569        group_snap_data = test_group_snap_data([self.volume_type],
570                                               self.group_type_id)
571        ctx = context.get_admin_context()
572
573        model_update, snapshots_model_update = (
574            self.driver.create_group_snapshot(ctx, group_snap_data, []))
575        self.assertEqual({'status': fields.GroupStatus.AVAILABLE},
576                         model_update)
577        self.assertEqual([], snapshots_model_update, 'Unexpected return data')
578
579        model_update, snapshots_model_update = (
580            self.driver.delete_group_snapshot(ctx, group_snap_data, []))
581        self.assertEqual({}, model_update, 'Unexpected return data')
582        self.assertEqual([], snapshots_model_update, 'Unexpected return data')
583
584
585class EMCCoprHDFCDriverTest(test.TestCase):
586
587    def setUp(self):
588        super(EMCCoprHDFCDriverTest, self).setUp()
589        self.create_coprhd_setup()
590
591    def create_coprhd_setup(self):
592
593        self.configuration = mock.Mock()
594        self.configuration.coprhd_hostname = "10.10.10.10"
595        self.configuration.coprhd_port = "4443"
596        self.configuration.volume_backend_name = "EMCCoprHDFCDriver"
597        self.configuration.coprhd_username = "user-name"
598        self.configuration.coprhd_password = "password"
599        self.configuration.coprhd_tenant = "tenant"
600        self.configuration.coprhd_project = "project"
601        self.configuration.coprhd_varray = "varray"
602        self.configuration.coprhd_emulate_snapshot = False
603
604        self.volume_type = self.create_coprhd_volume_type()
605        self.volume_type_id = self.volume_type.id
606        self.group_type = test_group_type_data()
607        self.group_type_id = self.group_type.id
608
609        self.mock_object(coprhd_fc.EMCCoprHDFCDriver,
610                         '_get_common_driver',
611                         self._get_mocked_common_driver)
612        self.driver = coprhd_fc.EMCCoprHDFCDriver(
613            configuration=self.configuration)
614
615    def tearDown(self):
616        self._cleanUp()
617        super(EMCCoprHDFCDriverTest, self).tearDown()
618
619    def _cleanUp(self):
620        self.delete_vipr_volume_type()
621
622    def create_coprhd_volume_type(self):
623        ctx = context.get_admin_context()
624        vipr_volume_type = volume_types.create(ctx,
625                                               "coprhd-volume-type",
626                                               {'CoprHD:VPOOL': 'vpool_vipr'})
627        return vipr_volume_type
628
629    def _get_mocked_common_driver(self):
630        return MockedEMCCoprHDDriverCommon(
631            protocol="FC",
632            default_backend_name="EMCViPRFCDriver",
633            configuration=self.configuration)
634
635    def delete_vipr_volume_type(self):
636        ctx = context.get_admin_context()
637        volume_types.destroy(ctx, self.volume_type_id)
638
639    def test_create_destroy(self):
640        volume = test_volume_data(self.volume_type_id)
641
642        self.driver.create_volume(volume)
643        self.driver.delete_volume(volume)
644
645    def test_get_volume_stats(self):
646        vol_stats = self.driver.get_volume_stats(True)
647        self.assertEqual('unknown', vol_stats['free_capacity_gb'])
648
649    def test_create_volume_clone(self):
650
651        src_volume_data = test_volume_data(self.volume_type_id)
652        clone_volume_data = test_clone_volume_data(self.volume_type_id)
653        self.driver.create_volume(src_volume_data)
654        self.driver.create_cloned_volume(clone_volume_data, src_volume_data)
655        self.driver.delete_volume(src_volume_data)
656        self.driver.delete_volume(clone_volume_data)
657
658    def test_create_destroy_snapshot(self):
659
660        volume_data = test_volume_data(self.volume_type_id)
661        snapshot_data = test_snapshot_data(
662            source_test_volume_data(self.volume_type_id))
663
664        self.driver.create_volume(volume_data)
665        self.driver.create_snapshot(snapshot_data)
666        self.driver.delete_snapshot(snapshot_data)
667        self.driver.delete_volume(volume_data)
668
669    def test_create_volume_from_snapshot(self):
670        src_vol_data = source_test_volume_data(self.volume_type_id)
671        self.driver.create_volume(src_vol_data)
672
673        volume_data = test_volume_data(self.volume_type_id)
674        snapshot_data = test_snapshot_data(src_vol_data)
675
676        self.driver.create_snapshot(snapshot_data)
677        self.driver.create_volume_from_snapshot(volume_data, snapshot_data)
678
679        self.driver.delete_snapshot(snapshot_data)
680        self.driver.delete_volume(src_vol_data)
681        self.driver.delete_volume(volume_data)
682
683    def test_extend_volume(self):
684        volume_data = test_volume_data(self.volume_type_id)
685        self.driver.create_volume(volume_data)
686        self.driver.extend_volume(volume_data, 2)
687        self.driver.delete_volume(volume_data)
688
689    def test_initialize_and_terminate_connection(self):
690
691        connector_data = get_connector_data()
692        volume_data = test_volume_data(self.volume_type_id)
693
694        self.driver.create_volume(volume_data)
695        res_initiatlize = self.driver.initialize_connection(
696            volume_data, connector_data)
697        expected_initialize = {'driver_volume_type': 'fibre_channel',
698                               'data': {'target_lun': 3,
699                                        'initiator_target_map':
700                                        {'1234567890543211':
701                                         ['1234567890123456',
702                                          '1234567890123456'],
703                                         '1234567890123456':
704                                         ['1234567890123456',
705                                          '1234567890123456']},
706                                        'target_wwn': ['1234567890123456',
707                                                       '1234567890123456'],
708                                        'target_discovered': False,
709                                        'volume_id': fake.VOLUME_ID}}
710        self.assertEqual(
711            expected_initialize, res_initiatlize, 'Unexpected return data')
712
713        res_terminate = self.driver.terminate_connection(
714            volume_data, connector_data)
715        expected_terminate = {'driver_volume_type': 'fibre_channel',
716                              'data': {'initiator_target_map':
717                                       {'1234567890543211':
718                                        ['1234567890123456',
719                                         '1234567890123456'],
720                                        '1234567890123456':
721                                        ['1234567890123456',
722                                         '1234567890123456']},
723                                       'target_wwn': ['1234567890123456',
724                                                      '1234567890123456']}}
725        self.assertEqual(
726            expected_terminate, res_terminate, 'Unexpected return data')
727
728        self.driver.delete_volume(volume_data)
729
730    @mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
731    def test_create_delete_empty_group(self, cg_ss_enabled):
732        cg_ss_enabled.side_effect = [True, True]
733        group_data = test_group_data([self.volume_type],
734                                     self.group_type_id)
735        ctx = context.get_admin_context()
736        self.driver.create_group(ctx, group_data)
737        model_update, volumes_model_update = (
738            self.driver.delete_group(ctx, group_data, []))
739        self.assertEqual([], volumes_model_update, 'Unexpected return data')
740
741    @mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
742    def test_create_update_delete_group(self, cg_ss_enabled):
743        cg_ss_enabled.side_effect = [True, True, True]
744        group_data = test_group_data([self.volume_type],
745                                     self.group_type_id)
746        ctx = context.get_admin_context()
747        self.driver.create_group(ctx, group_data)
748
749        volume = test_volume_data(self.volume_type_id)
750        self.driver.create_volume(volume)
751
752        model_update, ret1, ret2 = (
753            self.driver.update_group(ctx, group_data, [volume], []))
754
755        self.assertEqual({'status': fields.GroupStatus.AVAILABLE},
756                         model_update)
757
758        model_update, volumes_model_update = (
759            self.driver.delete_group(ctx, group_data, [volume]))
760        self.assertEqual({'status': fields.GroupStatus.AVAILABLE},
761                         model_update)
762        self.assertEqual([{'status': 'deleted', 'id': fake.VOLUME_ID}],
763                         volumes_model_update)
764
765    @mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
766    def test_create_delete_group_snap(self, cg_ss_enabled):
767        cg_ss_enabled.side_effect = [True, True]
768        group_snap_data = test_group_snap_data([self.volume_type],
769                                               self.group_type_id)
770        ctx = context.get_admin_context()
771
772        model_update, snapshots_model_update = (
773            self.driver.create_group_snapshot(ctx, group_snap_data, []))
774        self.assertEqual({'status': fields.GroupStatus.AVAILABLE},
775                         model_update)
776        self.assertEqual([], snapshots_model_update, 'Unexpected return data')
777
778        model_update, snapshots_model_update = (
779            self.driver.delete_group_snapshot(ctx, group_snap_data, []))
780        self.assertEqual({}, model_update, 'Unexpected return data')
781        self.assertEqual([], snapshots_model_update, 'Unexpected return data')
782
783
784class EMCCoprHDScaleIODriverTest(test.TestCase):
785
786    def setUp(self):
787        super(EMCCoprHDScaleIODriverTest, self).setUp()
788        self.create_coprhd_setup()
789
790    def create_coprhd_setup(self):
791
792        self.configuration = mock.Mock()
793        self.configuration.coprhd_hostname = "10.10.10.10"
794        self.configuration.coprhd_port = "4443"
795        self.configuration.volume_backend_name = "EMCCoprHDFCDriver"
796        self.configuration.coprhd_username = "user-name"
797        self.configuration.coprhd_password = "password"
798        self.configuration.coprhd_tenant = "tenant"
799        self.configuration.coprhd_project = "project"
800        self.configuration.coprhd_varray = "varray"
801        self.configuration.coprhd_scaleio_rest_gateway_host = "10.10.10.11"
802        self.configuration.coprhd_scaleio_rest_gateway_port = 443
803        self.configuration.coprhd_scaleio_rest_server_username = (
804            "scaleio_username")
805        self.configuration.coprhd_scaleio_rest_server_password = (
806            "scaleio_password")
807        self.configuration.scaleio_verify_server_certificate = False
808        self.configuration.scaleio_server_certificate_path = (
809            "/etc/scaleio/certs")
810
811        self.volume_type = self.create_coprhd_volume_type()
812        self.volume_type_id = self.volume_type.id
813        self.group_type = test_group_type_data()
814        self.group_type_id = self.group_type.id
815
816        self.mock_object(coprhd_scaleio.EMCCoprHDScaleIODriver,
817                         '_get_common_driver',
818                         self._get_mocked_common_driver)
819        self.mock_object(coprhd_scaleio.EMCCoprHDScaleIODriver,
820                         '_get_client_id',
821                         self._get_client_id)
822        self.driver = coprhd_scaleio.EMCCoprHDScaleIODriver(
823            configuration=self.configuration)
824
825    def tearDown(self):
826        self._cleanUp()
827        super(EMCCoprHDScaleIODriverTest, self).tearDown()
828
829    def _cleanUp(self):
830        self.delete_vipr_volume_type()
831
832    def create_coprhd_volume_type(self):
833        ctx = context.get_admin_context()
834        vipr_volume_type = volume_types.create(ctx,
835                                               "coprhd-volume-type",
836                                               {'CoprHD:VPOOL': 'vpool_vipr'})
837        return vipr_volume_type
838
839    def _get_mocked_common_driver(self):
840        return MockedEMCCoprHDDriverCommon(
841            protocol="scaleio",
842            default_backend_name="EMCCoprHDScaleIODriver",
843            configuration=self.configuration)
844
845    def _get_client_id(self, server_ip, server_port, server_username,
846                       server_password, sdc_ip):
847        return "bfdf432500000004"
848
849    def delete_vipr_volume_type(self):
850        ctx = context.get_admin_context()
851        volume_types.destroy(ctx, self.volume_type_id)
852
853    def test_create_destroy(self):
854        volume = test_volume_data(self.volume_type_id)
855
856        self.driver.create_volume(volume)
857        self.driver.delete_volume(volume)
858
859    def test_get_volume_stats(self):
860        vol_stats = self.driver.get_volume_stats(True)
861        self.assertEqual('unknown', vol_stats['free_capacity_gb'])
862
863    def test_create_volume_clone(self):
864
865        src_volume_data = test_volume_data(self.volume_type_id)
866        clone_volume_data = test_clone_volume_data(self.volume_type_id)
867        self.driver.create_volume(src_volume_data)
868        self.driver.create_cloned_volume(clone_volume_data, src_volume_data)
869        self.driver.delete_volume(src_volume_data)
870        self.driver.delete_volume(clone_volume_data)
871
872    def test_create_destroy_snapshot(self):
873
874        volume_data = test_volume_data(self.volume_type_id)
875        snapshot_data = test_snapshot_data(
876            source_test_volume_data(self.volume_type_id))
877
878        self.driver.create_volume(volume_data)
879        self.driver.create_snapshot(snapshot_data)
880        self.driver.delete_snapshot(snapshot_data)
881        self.driver.delete_volume(volume_data)
882
883    def test_create_volume_from_snapshot(self):
884        src_vol_data = source_test_volume_data(self.volume_type_id)
885        self.driver.create_volume(src_vol_data)
886
887        volume_data = test_volume_data(self.volume_type_id)
888        snapshot_data = test_snapshot_data(src_vol_data)
889
890        self.driver.create_snapshot(snapshot_data)
891        self.driver.create_volume_from_snapshot(volume_data, snapshot_data)
892
893        self.driver.delete_snapshot(snapshot_data)
894        self.driver.delete_volume(src_vol_data)
895        self.driver.delete_volume(volume_data)
896
897    def test_extend_volume(self):
898        volume_data = test_volume_data(self.volume_type_id)
899        self.driver.create_volume(volume_data)
900        self.driver.extend_volume(volume_data, 2)
901        self.driver.delete_volume(volume_data)
902
903    def test_initialize_and_terminate_connection(self):
904
905        connector_data = get_connector_data()
906        volume_data = test_volume_data(self.volume_type_id)
907
908        self.driver.create_volume(volume_data)
909        res_initiatlize = self.driver.initialize_connection(
910            volume_data, connector_data)
911        exp_name = res_initiatlize['data']['scaleIO_volname']
912        expected_initialize = {'data': {'bandwidthLimit': None,
913                                        'hostIP': '10.0.0.2',
914                                        'iopsLimit': None,
915                                        'scaleIO_volname': exp_name,
916                                        'scaleIO_volume_id': fake.PROVIDER_ID,
917                                        'serverIP': '10.10.10.11',
918                                        'serverPassword': 'scaleio_password',
919                                        'serverPort': 443,
920                                        'serverToken': None,
921                                        'serverUsername': 'scaleio_username'},
922                               'driver_volume_type': 'scaleio'}
923        self.assertEqual(
924            expected_initialize, res_initiatlize, 'Unexpected return data')
925
926        self.driver.terminate_connection(
927            volume_data, connector_data)
928        self.driver.delete_volume(volume_data)
929
930    @mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
931    def test_create_delete_empty_group(self, cg_ss_enabled):
932        cg_ss_enabled.side_effect = [True, True]
933        group_data = test_group_data([self.volume_type],
934                                     self.group_type_id)
935        ctx = context.get_admin_context()
936        self.driver.create_group(ctx, group_data)
937        model_update, volumes_model_update = (
938            self.driver.delete_group(ctx, group_data, []))
939        self.assertEqual([], volumes_model_update, 'Unexpected return data')
940
941    @mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
942    def test_create_update_delete_group(self, cg_ss_enabled):
943        cg_ss_enabled.side_effect = [True, True, True, True]
944        group_data = test_group_data([self.volume_type],
945                                     self.group_type_id)
946        ctx = context.get_admin_context()
947        self.driver.create_group(ctx, group_data)
948
949        volume = test_volume_data(self.volume_type_id)
950        self.driver.create_volume(volume)
951
952        model_update, ret1, ret2 = (
953            self.driver.update_group(ctx, group_data, [volume], []))
954
955        self.assertEqual({'status': fields.GroupStatus.AVAILABLE},
956                         model_update)
957
958        model_update, volumes_model_update = (
959            self.driver.delete_group(ctx, group_data, [volume]))
960        self.assertEqual({'status': fields.GroupStatus.AVAILABLE},
961                         model_update)
962        self.assertEqual([{'status': 'deleted', 'id': fake.VOLUME_ID}],
963                         volumes_model_update)
964
965    @mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
966    def test_create_delete_group_snap(self, cg_ss_enabled):
967        cg_ss_enabled.side_effect = [True, True]
968        group_snap_data = test_group_snap_data([self.volume_type],
969                                               self.group_type_id)
970        ctx = context.get_admin_context()
971
972        model_update, snapshots_model_update = (
973            self.driver.create_group_snapshot(ctx, group_snap_data, []))
974        self.assertEqual({'status': fields.GroupStatus.AVAILABLE},
975                         model_update)
976        self.assertEqual([], snapshots_model_update, 'Unexpected return data')
977
978        model_update, snapshots_model_update = (
979            self.driver.delete_group_snapshot(ctx, group_snap_data, []))
980        self.assertEqual({}, model_update, 'Unexpected return data')
981        self.assertEqual([], snapshots_model_update, 'Unexpected return data')
982