Example #1
0
    def _configure_driver(self):

        configuration = conf.Configuration(None, None)

        # initialize the elasticenter iscsi driver
        self.driver = CloudByteISCSIDriver(configuration=configuration)

        # override some parts of driver configuration
        self.driver.configuration.cb_tsm_name = 'openstack'
        self.driver.configuration.cb_account_name = 'CustomerA'
Example #2
0
    def _configure_driver(self):

        configuration = conf.Configuration(None, None)

        # initialize the elasticenter iscsi driver
        self.driver = CloudByteISCSIDriver(configuration=configuration)

        # override some parts of driver configuration
        self.driver.configuration.tsm_name = 'openstack'
        self.driver.configuration.cb_account_name = 'CustomerA'
Example #3
0
class CloudByteISCSIDriverTestCase(testtools.TestCase):
    def setUp(self):
        super(CloudByteISCSIDriverTestCase, self).setUp()
        self._configure_driver()

    def _configure_driver(self):

        configuration = conf.Configuration(None, None)

        # initialize the elasticenter iscsi driver
        self.driver = CloudByteISCSIDriver(configuration=configuration)

        # override some parts of driver configuration
        self.driver.configuration.cb_tsm_name = 'openstack'
        self.driver.configuration.cb_account_name = 'CustomerA'

    def _side_effect_api_req(self, cmd, params, version='1.0'):
        """This is a side effect function.

        The return value is determined based on cmd argument.
        The signature matches exactly with the method it tries
        to mock.
        """
        return MAP_COMMAND_TO_FAKE_RESPONSE[cmd]

    def _side_effect_api_req_to_create_vol(self, cmd, params, version='1.0'):
        """This is a side effect function."""
        if cmd == 'createVolume':
            return {}

        return MAP_COMMAND_TO_FAKE_RESPONSE[cmd]

    def _side_effect_api_req_to_query_asyncjob(self,
                                               cmd,
                                               params,
                                               version='1.0'):
        """This is a side effect function."""

        if cmd == 'queryAsyncJobResult':
            return {'queryasyncjobresultresponse': {'jobstatus': 0}}

        return MAP_COMMAND_TO_FAKE_RESPONSE[cmd]

    def _side_effect_api_req_to_list_tsm(self, cmd, params, version='1.0'):
        """This is a side effect function."""
        if cmd == 'listTsm':
            return {}

        return MAP_COMMAND_TO_FAKE_RESPONSE[cmd]

    def _side_effect_api_req_to_list_filesystem(self,
                                                cmd,
                                                params,
                                                version='1.0'):
        """This is a side effect function."""
        if cmd == 'listFileSystem':
            return {}

        return MAP_COMMAND_TO_FAKE_RESPONSE[cmd]

    def _side_effect_api_req_to_list_vol_iscsi_service(self,
                                                       cmd,
                                                       params,
                                                       version='1.0'):
        """This is a side effect function."""
        if cmd == 'listVolumeiSCSIService':
            return {}

        return MAP_COMMAND_TO_FAKE_RESPONSE[cmd]

    def _side_effect_api_req_to_list_iscsi_initiator(self,
                                                     cmd,
                                                     params,
                                                     version='1.0'):
        """This is a side effect function."""
        if cmd == 'listiSCSIInitiator':
            return {}

        return MAP_COMMAND_TO_FAKE_RESPONSE[cmd]

    def _side_effect_create_vol_from_snap(self, cloned_volume, snapshot):
        """This is a side effect function."""
        return {}

    def _side_effect_create_snapshot(self, snapshot):
        """This is a side effect function."""
        model_update = {}
        model_update['provider_id'] = "devpool1/acc1openstacktsm/DS1@DS1Snap1"
        return model_update

    def _side_effect_get_connection(self, host, url):
        """This is a side effect function."""

        return_obj = {}

        return_obj['http_status'] = 200

        # mock the response data
        return_obj['data'] = MAP_COMMAND_TO_FAKE_RESPONSE['listTsm']
        return_obj['error'] = None

        return return_obj

    def _side_effect_get_err_connection(self, host, url):
        """This is a side effect function."""

        return_obj = {}

        return_obj['http_status'] = 500

        # mock the response data
        return_obj['data'] = None
        return_obj['error'] = "Http status: 500, Error: Elasticenter "
        "is not available."

        return return_obj

    def _side_effect_get_err_connection2(self, host, url):
        """This is a side effect function."""

        msg = ("Error executing CloudByte API %(cmd)s , Error: %(err)s" % {
            'cmd': 'MockTest',
            'err': 'Error'
        })
        raise exception.VolumeBackendAPIException(msg)

    def _get_fake_volume_id(self):

        # Get the filesystems
        fs_list = MAP_COMMAND_TO_FAKE_RESPONSE['listFileSystem']
        filesystems = fs_list['listFilesystemResponse']['filesystem']

        # Get the volume id from the first filesystem
        volume_id = filesystems[0]['id']

        return volume_id

    @mock.patch.object(CloudByteISCSIDriver,
                       '_execute_and_get_response_details')
    def test_api_request_for_cloudbyte(self, mock_conn):

        # Test - I

        # configure the mocks with respective side-effects
        mock_conn.side_effect = self._side_effect_get_connection

        # run the test
        data = self.driver._api_request_for_cloudbyte('listTsm', {})

        # assert the data attributes
        self.assertEqual(1, data['listTsmResponse']['count'])

        # Test - II

        # configure the mocks with side-effects
        mock_conn.reset_mock()
        mock_conn.side_effect = self._side_effect_get_err_connection

        # run the test
        with ExpectedException(
                exception.VolumeBackendAPIException,
                'Bad or unexpected response from the storage volume '
                'backend API: Failed to execute CloudByte API'):
            self.driver._api_request_for_cloudbyte('listTsm', {})

        # Test - III

        # configure the mocks with side-effects
        mock_conn.reset_mock()
        mock_conn.side_effect = self._side_effect_get_err_connection2

        # run the test
        with ExpectedException(exception.VolumeBackendAPIException,
                               'Error executing CloudByte API'):
            self.driver._api_request_for_cloudbyte('listTsm', {})

    @mock.patch.object(CloudByteISCSIDriver, '_api_request_for_cloudbyte')
    def test_delete_volume(self, mock_api_req):

        # prepare the dependencies
        fake_volume_id = self._get_fake_volume_id()
        volume = {'id': fake_volume_id, 'provider_id': fake_volume_id}

        # Test-I

        mock_api_req.side_effect = self._side_effect_api_req

        # run the test
        self.driver.delete_volume(volume)

        # assert that 2 api calls were invoked
        self.assertEqual(2, mock_api_req.call_count)

        # Test-II

        # reset & re-configure mock
        volume['provider_id'] = None
        mock_api_req.reset_mock()
        mock_api_req.side_effect = self._side_effect_api_req

        # run the test
        self.driver.delete_volume(volume)

        # assert that no api calls were invoked
        self.assertEqual(0, mock_api_req.call_count)

    @mock.patch.object(CloudByteISCSIDriver, '_api_request_for_cloudbyte')
    def test_delete_snapshot(self, mock_api_req):

        snapshot = {
            'id': 'SomeID',
            'provider_id': 'devpool1/acc1openstacktsm/DS1@DS1Snap1',
            'display_name': 'DS1Snap1',
            'volume_id': 'SomeVol',
            'volume': {
                'display_name': 'DS1'
            }
        }

        # Test - I

        # now run the test
        self.driver.delete_snapshot(snapshot)

        # assert that 1 api call was invoked
        self.assertEqual(1, mock_api_req.call_count)

        # Test - II

        # reconfigure the dependencies
        snapshot['provider_id'] = None

        # reset & reconfigure the mock
        mock_api_req.reset_mock()
        mock_api_req.side_effect = self._side_effect_api_req

        # now run the test
        self.driver.delete_snapshot(snapshot)

        # assert that no api calls were invoked
        self.assertEqual(0, mock_api_req.call_count)

    @mock.patch.object(CloudByteISCSIDriver, '_api_request_for_cloudbyte')
    def test_create_snapshot(self, mock_api_req):

        # prepare the dependencies
        fake_volume_id = self._get_fake_volume_id()

        snapshot = {
            'id': 'SomeID',
            'display_name': 'DS1Snap1',
            'volume_id': 'SomeVol',
            'volume': {
                'display_name': 'DS1',
                'provider_id': fake_volume_id
            }
        }

        # Test - I

        # configure the mocks with respective side-effects
        mock_api_req.side_effect = self._side_effect_api_req

        # now run the test
        self.driver.create_snapshot(snapshot)

        # assert that 2 api calls were invoked
        self.assertEqual(2, mock_api_req.call_count)

        # Test - II

        # reconfigure the dependencies
        snapshot['volume']['provider_id'] = None

        # reset & reconfigure the mock
        mock_api_req.reset_mock()
        mock_api_req.side_effect = self._side_effect_api_req

        # now run the test & assert the exception
        with ExpectedException(
                exception.VolumeBackendAPIException,
                'Bad or unexpected response from the storage volume '
                'backend API: Failed to create snapshot'):
            self.driver.create_snapshot(snapshot)

        # assert that no api calls were invoked
        self.assertEqual(0, mock_api_req.call_count)

    @mock.patch.object(CloudByteISCSIDriver, '_api_request_for_cloudbyte')
    def test_create_volume(self, mock_api_req):

        # prepare the dependencies
        fake_volume_id = self._get_fake_volume_id()

        volume = {'id': fake_volume_id, 'size': 22}

        # Test - I

        # configure the mocks with respective side-effects
        mock_api_req.side_effect = self._side_effect_api_req

        # now run the test
        provider_details = self.driver.create_volume(volume)

        # assert equality checks for certain configuration attributes
        self.assertEqual('openstack', self.driver.configuration.cb_tsm_name)
        self.assertEqual('CustomerA',
                         self.driver.configuration.cb_account_name)
        self.assertThat(provider_details['provider_location'],
                        Contains('172.16.50.35:3260'))

        # assert that 9 api calls were invoked
        self.assertEqual(9, mock_api_req.call_count)

        # Test - II

        # reconfigure the dependencies
        volume['id'] = 'NotExists'
        del volume['size']

        # reset & reconfigure the mock
        mock_api_req.reset_mock()
        mock_api_req.side_effect = self._side_effect_api_req

        # now run the test & assert the exception
        with ExpectedException(
                exception.VolumeBackendAPIException,
                "Bad or unexpected response from the storage volume "
                "backend API: Volume \[NotExists\] not found in "
                "CloudByte storage."):
            self.driver.create_volume(volume)

        # Test - III

        # reconfigure the dependencies
        volume['id'] = 'abc'

        # reset the mocks
        mock_api_req.reset_mock()

        # configure or re-configure the mocks
        mock_api_req.side_effect = self._side_effect_api_req_to_create_vol

        # now run the test & assert the exception
        with ExpectedException(
                exception.VolumeBackendAPIException,
                'Bad or unexpected response from the storage volume '
                'backend API: Null response received while '
                'creating volume'):
            self.driver.create_volume(volume)

        # Test - IV

        # reconfigure the dependencies
        # reset the mocks
        mock_api_req.reset_mock()

        # configure or re-configure the mocks
        mock_api_req.side_effect = self._side_effect_api_req_to_list_filesystem

        # now run the test
        with ExpectedException(
                exception.VolumeBackendAPIException,
                "Bad or unexpected response from the storage volume "
                "backend API: Null response received from CloudByte's "
                "list filesystem."):
            self.driver.create_volume(volume)

        # Test - VI

        volume['id'] = fake_volume_id
        # reconfigure the dependencies
        # reset the mocks
        mock_api_req.reset_mock()

        # configure or re-configure the mocks
        mock_api_req.side_effect = (
            self._side_effect_api_req_to_list_vol_iscsi_service)

        # now run the test
        with ExpectedException(
                exception.VolumeBackendAPIException,
                "Bad or unexpected response from the storage volume "
                "backend API: Null response received from CloudByte's "
                "list volume iscsi service."):
            self.driver.create_volume(volume)

        # Test - VII

        # reconfigure the dependencies
        # reset the mocks
        mock_api_req.reset_mock()

        # configure or re-configure the mocks
        mock_api_req.side_effect = (
            self._side_effect_api_req_to_list_iscsi_initiator)

        # now run the test
        with ExpectedException(
                exception.VolumeBackendAPIException,
                "Bad or unexpected response from the storage volume "
                "backend API: Null response received from CloudByte's "
                "list iscsi initiators."):
            self.driver.create_volume(volume)

    @mock.patch.object(CloudByteISCSIDriver, '_api_request_for_cloudbyte')
    @mock.patch.object(CloudByteISCSIDriver, 'create_volume_from_snapshot')
    @mock.patch.object(CloudByteISCSIDriver, 'create_snapshot')
    def test_create_cloned_volume(self, mock_create_snapshot,
                                  mock_create_vol_from_snap, mock_api_req):

        # prepare the input test data
        fake_volume_id = self._get_fake_volume_id()

        src_volume = {'display_name': 'DS1Snap1'}

        cloned_volume = {
            'source_volid': fake_volume_id,
            'id': 'SomeNewID',
            'display_name': 'CloneOfDS1Snap1'
        }

        # Test - I

        # configure the mocks with respective sideeffects
        mock_api_req.side_effect = self._side_effect_api_req
        mock_create_vol_from_snap.side_effect = (
            self._side_effect_create_vol_from_snap)
        mock_create_snapshot.side_effect = (self._side_effect_create_snapshot)

        # now run the test
        self.driver.create_cloned_volume(cloned_volume, src_volume)

        # assert that n api calls were invoked
        self.assertEqual(0, mock_api_req.call_count)

    @mock.patch.object(CloudByteISCSIDriver, '_api_request_for_cloudbyte')
    def test_create_volume_from_snapshot(self, mock_api_req):

        # prepare the input test data
        fake_volume_id = self._get_fake_volume_id()

        snapshot = {
            'volume_id': fake_volume_id,
            'provider_id': 'devpool1/acc1openstacktsm/DS1@DS1Snap1',
            'id': 'SomeSnapID',
            'volume': {
                'provider_id': fake_volume_id
            }
        }

        cloned_volume = {
            'display_name': 'CloneOfDS1Snap1',
            'id': 'ClonedVolID'
        }

        # Test - I

        # configure the mocks with respective side-effects
        mock_api_req.side_effect = self._side_effect_api_req

        # now run the test
        self.driver.create_volume_from_snapshot(cloned_volume, snapshot)

        # assert n api calls were invoked
        self.assertEqual(1, mock_api_req.call_count)

    @mock.patch.object(CloudByteISCSIDriver, '_api_request_for_cloudbyte')
    def test_extend_volume(self, mock_api_req):

        # prepare the input test data
        fake_volume_id = self._get_fake_volume_id()

        volume = {'id': 'SomeID', 'provider_id': fake_volume_id}

        new_size = '2'

        # Test - I

        # configure the mock with respective side-effects
        mock_api_req.side_effect = self._side_effect_api_req

        # now run the test
        self.driver.extend_volume(volume, new_size)

        # assert n api calls were invoked
        self.assertEqual(1, mock_api_req.call_count)

    @mock.patch.object(CloudByteISCSIDriver, '_api_request_for_cloudbyte')
    def test_create_export(self, mock_api_req):

        # prepare the input test data

        # configure the mocks with respective side-effects
        mock_api_req.side_effect = self._side_effect_api_req

        # now run the test
        model_update = self.driver.create_export({}, {})

        # assert the result
        self.assertEqual(None, model_update['provider_auth'])

    @mock.patch.object(CloudByteISCSIDriver, '_api_request_for_cloudbyte')
    def test_ensure_export(self, mock_api_req):

        # prepare the input test data

        # configure the mock with respective side-effects
        mock_api_req.side_effect = self._side_effect_api_req

        # now run the test
        model_update = self.driver.ensure_export({}, {})

        # assert the result to have a provider_auth attribute
        self.assertEqual(None, model_update['provider_auth'])

    @mock.patch.object(CloudByteISCSIDriver, '_api_request_for_cloudbyte')
    def test_get_volume_stats(self, mock_api_req):

        # prepare the input test data

        # configure the mock with a side-effect
        mock_api_req.side_effect = self._side_effect_api_req

        # Test - I

        # run the test
        vol_stats = self.driver.get_volume_stats()

        # assert 0 api calls were invoked
        self.assertEqual(0, mock_api_req.call_count)

        # Test - II

        # run the test with refresh as True
        vol_stats = self.driver.get_volume_stats(refresh=True)

        # assert n api calls were invoked
        self.assertEqual(1, mock_api_req.call_count)

        # assert the result attributes with respective values
        self.assertEqual(1024.0, vol_stats['total_capacity_gb'])
        self.assertEqual(824.0, vol_stats['free_capacity_gb'])
        self.assertEqual(0, vol_stats['reserved_percentage'])
        self.assertEqual('CloudByte', vol_stats['vendor_name'])
        self.assertEqual('iSCSI', vol_stats['storage_protocol'])

        # Test - III

        # configure the mocks with side-effect
        mock_api_req.reset_mock()
        mock_api_req.side_effect = self._side_effect_api_req_to_list_tsm

        # run the test with refresh as True
        with ExpectedException(
                exception.VolumeBackendAPIException,
                "Bad or unexpected response from the storage volume "
                "backend API: No response was received from CloudByte "
                "storage list tsm API call."):
            self.driver.get_volume_stats(refresh=True)
Example #4
0
class CloudByteISCSIDriverTestCase(testtools.TestCase):

    def setUp(self):
        super(CloudByteISCSIDriverTestCase, self).setUp()
        self._configure_driver()

    def _configure_driver(self):

        configuration = conf.Configuration(None, None)

        # initialize the elasticenter iscsi driver
        self.driver = CloudByteISCSIDriver(configuration=configuration)

        # override some parts of driver configuration
        self.driver.configuration.tsm_name = 'openstack'
        self.driver.configuration.cb_account_name = 'CustomerA'

    def _side_effect_api_req(self, cmd, params, version='1.0'):
        """This is a side effect function.

        The return value is determined based on cmd argument.
        The signature matches exactly with the method it tries
        to mock.
        """
        return MAP_COMMAND_TO_FAKE_RESPONSE[cmd]

    def _side_effect_api_req_to_create_vol(self, cmd, params, version='1.0'):
        """This is a side effect function."""
        if cmd == 'createVolume':
            return {}

        return MAP_COMMAND_TO_FAKE_RESPONSE[cmd]

    def _side_effect_api_req_to_query_asyncjob(
            self, cmd, params, version='1.0'):
        """This is a side effect function."""

        if cmd == 'queryAsyncJobResult':
            return {'queryasyncjobresultresponse': {'jobstatus': 0}}

        return MAP_COMMAND_TO_FAKE_RESPONSE[cmd]

    def _side_effect_api_req_to_list_tsm(self, cmd, params, version='1.0'):
        """This is a side effect function."""
        if cmd == 'listTsm':
            return {}

        return MAP_COMMAND_TO_FAKE_RESPONSE[cmd]

    def _side_effect_api_req_to_list_filesystem(
            self, cmd, params, version='1.0'):
        """This is a side effect function."""
        if cmd == 'listFileSystem':
            return {}

        return MAP_COMMAND_TO_FAKE_RESPONSE[cmd]

    def _side_effect_api_req_to_list_vol_iscsi_service(
            self, cmd, params, version='1.0'):
        """This is a side effect function."""
        if cmd == 'listVolumeiSCSIService':
            return {}

        return MAP_COMMAND_TO_FAKE_RESPONSE[cmd]

    def _side_effect_api_req_to_list_iscsi_initiator(
            self, cmd, params, version='1.0'):
        """This is a side effect function."""
        if cmd == 'listiSCSIInitiator':
            return {}

        return MAP_COMMAND_TO_FAKE_RESPONSE[cmd]

    def _side_effect_create_vol_from_snap(self, cloned_volume, snapshot):
        """This is a side effect function."""
        return {}

    def _side_effect_create_snapshot(self, snapshot):
        """This is a side effect function."""
        model_update = {}
        model_update['provider_id'] = "devpool1/acc1openstacktsm/DS1@DS1Snap1"
        return model_update

    def _side_effect_get_connection(self, host, url):
        """This is a side effect function."""

        return_obj = {}

        return_obj['http_status'] = 200

        # mock the response data
        return_obj['data'] = MAP_COMMAND_TO_FAKE_RESPONSE['listTsm']
        return_obj['error'] = None

        return return_obj

    def _side_effect_get_err_connection(self, host, url):
        """This is a side effect function."""

        return_obj = {}

        return_obj['http_status'] = 500

        # mock the response data
        return_obj['data'] = None
        return_obj['error'] = "Http status: 500, Error: Elasticenter "
        "is not available."

        return return_obj

    def _side_effect_get_err_connection2(self, host, url):
        """This is a side effect function."""

        msg = ("Error executing CloudByte API %(cmd)s , Error: %(err)s" %
               {'cmd': 'MockTest', 'err': 'Error'})
        raise exception.VolumeBackendAPIException(msg)

    def _get_fake_volume_id(self):

        # Get the filesystems
        fs_list = MAP_COMMAND_TO_FAKE_RESPONSE['listFileSystem']
        filesystems = fs_list['listFilesystemResponse']['filesystem']

        # Get the volume id from the first filesystem
        volume_id = filesystems[0]['id']

        return volume_id

    @mock.patch.object(CloudByteISCSIDriver,
                       '_execute_and_get_response_details')
    def test_api_request_for_cloudbyte(self, mock_conn):

        # Test - I

        # configure the mocks with respective side-effects
        mock_conn.side_effect = self._side_effect_get_connection

        # run the test
        data = self.driver._api_request_for_cloudbyte('listTsm', {})

        # assert the data attributes
        self.assertEqual(1, data['listTsmResponse']['count'])

        # Test - II

        # configure the mocks with side-effects
        mock_conn.reset_mock()
        mock_conn.side_effect = self._side_effect_get_err_connection

        # run the test
        with ExpectedException(
                exception.VolumeBackendAPIException,
                'Bad or unexpected response from the storage volume '
                'backend API: Failed to execute CloudByte API'):
            self.driver._api_request_for_cloudbyte('listTsm', {})

        # Test - III

        # configure the mocks with side-effects
        mock_conn.reset_mock()
        mock_conn.side_effect = self._side_effect_get_err_connection2

        # run the test
        with ExpectedException(
                exception.VolumeBackendAPIException,
                'Error executing CloudByte API'):
            self.driver._api_request_for_cloudbyte('listTsm', {})

    @mock.patch.object(CloudByteISCSIDriver,
                       '_api_request_for_cloudbyte')
    def test_delete_volume(self, mock_api_req):

        # prepare the dependencies
        fake_volume_id = self._get_fake_volume_id()
        volume = {'id': fake_volume_id, 'provider_id': fake_volume_id}

        # Test-I

        mock_api_req.side_effect = self._side_effect_api_req

        # run the test
        self.driver.delete_volume(volume)

        # assert that 2 api calls were invoked
        self.assertEqual(2, mock_api_req.call_count)

        # Test-II

        # reset & re-configure mock
        volume['provider_id'] = None
        mock_api_req.reset_mock()
        mock_api_req.side_effect = self._side_effect_api_req

        # run the test
        self.driver.delete_volume(volume)

        # assert that no api calls were invoked
        self.assertEqual(0, mock_api_req.call_count)

    @mock.patch.object(CloudByteISCSIDriver,
                       '_api_request_for_cloudbyte')
    def test_delete_snapshot(self, mock_api_req):

        snapshot = {
            'id': 'SomeID',
            'provider_id': 'devpool1/acc1openstacktsm/DS1@DS1Snap1',
            'display_name': 'DS1Snap1',
            'volume_id': 'SomeVol',
            'volume': {
                'display_name': 'DS1'
            }

        }

        # Test - I

        # now run the test
        self.driver.delete_snapshot(snapshot)

        # assert that 1 api call was invoked
        self.assertEqual(1, mock_api_req.call_count)

        # Test - II

        # reconfigure the dependencies
        snapshot['provider_id'] = None

        # reset & reconfigure the mock
        mock_api_req.reset_mock()
        mock_api_req.side_effect = self._side_effect_api_req

        # now run the test
        self.driver.delete_snapshot(snapshot)

        # assert that no api calls were invoked
        self.assertEqual(0, mock_api_req.call_count)

    @mock.patch.object(CloudByteISCSIDriver,
                       '_api_request_for_cloudbyte')
    def test_create_snapshot(self, mock_api_req):

        # prepare the dependencies
        fake_volume_id = self._get_fake_volume_id()

        snapshot = {
            'id': 'SomeID',
            'display_name': 'DS1Snap1',
            'volume_id': 'SomeVol',
            'volume': {
                'display_name': 'DS1',
                'provider_id': fake_volume_id

            }
        }

        # Test - I

        # configure the mocks with respective side-effects
        mock_api_req.side_effect = self._side_effect_api_req

        # now run the test
        self.driver.create_snapshot(snapshot)

        # assert that 2 api calls were invoked
        self.assertEqual(2, mock_api_req.call_count)

        # Test - II

        # reconfigure the dependencies
        snapshot['volume']['provider_id'] = None

        # reset & reconfigure the mock
        mock_api_req.reset_mock()
        mock_api_req.side_effect = self._side_effect_api_req

        # now run the test & assert the exception
        with ExpectedException(
                exception.VolumeBackendAPIException,
                'Bad or unexpected response from the storage volume '
                'backend API: Failed to create snapshot'):
            self.driver.create_snapshot(snapshot)

        # assert that no api calls were invoked
        self.assertEqual(0, mock_api_req.call_count)

    @mock.patch.object(CloudByteISCSIDriver,
                       '_api_request_for_cloudbyte')
    def test_create_volume(self, mock_api_req):

        # prepare the dependencies
        fake_volume_id = self._get_fake_volume_id()

        volume = {
            'id': fake_volume_id,
            'size': 22
        }

        # Test - I

        # configure the mocks with respective side-effects
        mock_api_req.side_effect = self._side_effect_api_req

        # now run the test
        provider_details = self.driver.create_volume(volume)

        # assert equality checks for certain configuration attributes
        self.assertEqual(
            'openstack', self.driver.configuration.tsm_name)
        self.assertEqual(
            'CustomerA', self.driver.configuration.cb_account_name)
        self.assertThat(
            provider_details['provider_location'],
            Contains('172.16.50.35:3260'))

        # assert that 9 api calls were invoked
        self.assertEqual(9, mock_api_req.call_count)

        # Test - II

        # reconfigure the dependencies
        volume['id'] = 'NotExists'
        del volume['size']

        # reset & reconfigure the mock
        mock_api_req.reset_mock()
        mock_api_req.side_effect = self._side_effect_api_req

        # now run the test & assert the exception
        with ExpectedException(
                exception.VolumeBackendAPIException,
                "Bad or unexpected response from the storage volume "
                "backend API: Volume \[NotExists\] not found in "
                "CloudByte storage."):
            self.driver.create_volume(volume)

        # Test - III

        # reconfigure the dependencies
        volume['id'] = 'abc'

        # reset the mocks
        mock_api_req.reset_mock()

        # configure or re-configure the mocks
        mock_api_req.side_effect = self._side_effect_api_req_to_create_vol

        # now run the test & assert the exception
        with ExpectedException(
                exception.VolumeBackendAPIException,
                'Bad or unexpected response from the storage volume '
                'backend API: Null response received while '
                'creating volume'):
            self.driver.create_volume(volume)

        # Test - IV

        # reconfigure the dependencies
        # reset the mocks
        mock_api_req.reset_mock()

        # configure or re-configure the mocks
        mock_api_req.side_effect = self._side_effect_api_req_to_list_filesystem

        # now run the test
        with ExpectedException(
                exception.VolumeBackendAPIException,
                "Bad or unexpected response from the storage volume "
                "backend API: Null response received from CloudByte's "
                "list filesystem."):
            self.driver.create_volume(volume)

        # Test - VI

        volume['id'] = fake_volume_id
        # reconfigure the dependencies
        # reset the mocks
        mock_api_req.reset_mock()

        # configure or re-configure the mocks
        mock_api_req.side_effect = (
            self._side_effect_api_req_to_list_vol_iscsi_service)

        # now run the test
        with ExpectedException(
                exception.VolumeBackendAPIException,
                "Bad or unexpected response from the storage volume "
                "backend API: Null response received from CloudByte's "
                "list volume iscsi service."):
            self.driver.create_volume(volume)

        # Test - VII

        # reconfigure the dependencies
        # reset the mocks
        mock_api_req.reset_mock()

        # configure or re-configure the mocks
        mock_api_req.side_effect = (
            self._side_effect_api_req_to_list_iscsi_initiator)

        # now run the test
        with ExpectedException(
                exception.VolumeBackendAPIException,
                "Bad or unexpected response from the storage volume "
                "backend API: Null response received from CloudByte's "
                "list iscsi initiators."):
            self.driver.create_volume(volume)

    @mock.patch.object(CloudByteISCSIDriver,
                       '_api_request_for_cloudbyte')
    @mock.patch.object(CloudByteISCSIDriver,
                       'create_volume_from_snapshot')
    @mock.patch.object(CloudByteISCSIDriver,
                       'create_snapshot')
    def test_create_cloned_volume(self, mock_create_snapshot,
                                  mock_create_vol_from_snap, mock_api_req):

        # prepare the input test data
        fake_volume_id = self._get_fake_volume_id()

        src_volume = {'display_name': 'DS1Snap1'}

        cloned_volume = {
            'source_volid': fake_volume_id,
            'id': 'SomeNewID',
            'display_name': 'CloneOfDS1Snap1'
        }

        # Test - I

        # configure the mocks with respective sideeffects
        mock_api_req.side_effect = self._side_effect_api_req
        mock_create_vol_from_snap.side_effect = (
            self._side_effect_create_vol_from_snap)
        mock_create_snapshot.side_effect = (
            self._side_effect_create_snapshot)

        # now run the test
        self.driver.create_cloned_volume(cloned_volume, src_volume)

        # assert that n api calls were invoked
        self.assertEqual(0, mock_api_req.call_count)

    @mock.patch.object(CloudByteISCSIDriver,
                       '_api_request_for_cloudbyte')
    def test_create_volume_from_snapshot(self, mock_api_req):

        # prepare the input test data
        fake_volume_id = self._get_fake_volume_id()

        snapshot = {
            'volume_id': fake_volume_id,
            'provider_id': 'devpool1/acc1openstacktsm/DS1@DS1Snap1',
            'id': 'SomeSnapID',
            'volume': {
                'provider_id': fake_volume_id
            }
        }

        cloned_volume = {
            'display_name': 'CloneOfDS1Snap1',
            'id': 'ClonedVolID'
        }

        # Test - I

        # configure the mocks with respective side-effects
        mock_api_req.side_effect = self._side_effect_api_req

        # now run the test
        self.driver.create_volume_from_snapshot(cloned_volume, snapshot)

        # assert n api calls were invoked
        self.assertEqual(1, mock_api_req.call_count)

    @mock.patch.object(CloudByteISCSIDriver,
                       '_api_request_for_cloudbyte')
    def test_extend_volume(self, mock_api_req):

        # prepare the input test data
        fake_volume_id = self._get_fake_volume_id()

        volume = {
            'id': 'SomeID',
            'provider_id': fake_volume_id
        }

        new_size = '2'

        # Test - I

        # configure the mock with respective side-effects
        mock_api_req.side_effect = self._side_effect_api_req

        # now run the test
        self.driver.extend_volume(volume, new_size)

        # assert n api calls were invoked
        self.assertEqual(1, mock_api_req.call_count)

    @mock.patch.object(CloudByteISCSIDriver,
                       '_api_request_for_cloudbyte')
    def test_create_export(self, mock_api_req):

        # prepare the input test data

        # configure the mocks with respective side-effects
        mock_api_req.side_effect = self._side_effect_api_req

        # now run the test
        model_update = self.driver.create_export({}, {})

        # assert the result
        self.assertEqual(None, model_update['provider_auth'])

    @mock.patch.object(CloudByteISCSIDriver,
                       '_api_request_for_cloudbyte')
    def test_ensure_export(self, mock_api_req):

        # prepare the input test data

        # configure the mock with respective side-effects
        mock_api_req.side_effect = self._side_effect_api_req

        # now run the test
        model_update = self.driver.ensure_export({}, {})

        # assert the result to have a provider_auth attribute
        self.assertEqual(None, model_update['provider_auth'])

    @mock.patch.object(CloudByteISCSIDriver,
                       '_api_request_for_cloudbyte')
    def test_get_volume_stats(self, mock_api_req):

        # prepare the input test data

        # configure the mock with a side-effect
        mock_api_req.side_effect = self._side_effect_api_req

        # Test - I

        # run the test
        vol_stats = self.driver.get_volume_stats()

        # assert 0 api calls were invoked
        self.assertEqual(0, mock_api_req.call_count)

        # Test - II

        # run the test with refresh as True
        vol_stats = self.driver.get_volume_stats(refresh=True)

        # assert n api calls were invoked
        self.assertEqual(1, mock_api_req.call_count)

        # assert the result attributes with respective values
        self.assertEqual(0, vol_stats['reserved_percentage'])
        self.assertEqual('CloudByte', vol_stats['vendor_name'])
        self.assertEqual('iSCSI', vol_stats['storage_protocol'])

        # Test - III

        # configure the mocks with side-effect
        mock_api_req.reset_mock()
        mock_api_req.side_effect = self._side_effect_api_req_to_list_tsm

        # run the test with refresh as True
        with ExpectedException(
                exception.VolumeBackendAPIException,
                "Bad or unexpected response from the storage volume "
                "backend API: No response was received from CloudByte "
                "storage list tsm API call."):
            self.driver.get_volume_stats(refresh=True)