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