def setUp(self):
     self.fqdn = "fqdn"
     self.servicer = ControllerServicer(self.fqdn)
class TestControllerServerUnPublishVolume(unittest.TestCase):

    @patch("controller.array_action.array_mediator_xiv.XIVArrayMediator._connect")
    def setUp(self, connect):
        self.fqdn = "fqdn"
        self.hostname = "hostname"
        self.mediator = XIVArrayMediator("user", "password", self.fqdn)
        self.mediator.client = Mock()

        self.mediator.get_host_by_host_identifiers = Mock()
        self.mediator.get_host_by_host_identifiers.return_value = self.hostname, ["iscsi"]

        self.mediator.unmap_volume = Mock()
        self.mediator.unmap_volume.return_value = None

        self.servicer = ControllerServicer(self.fqdn)

        self.request = Mock()
        arr_type = XIVArrayMediator.array_type
        self.request.volume_id = "{}:wwn1".format(arr_type)
        self.request.node_id = "hostname;iqn1;500143802426baf4"
        self.request.secrets = {"username": "******", "password": "******", "management_address": "mg"}
        self.request.volume_context = {}

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    def test_unpublish_volume_success(self, enter):
        enter.return_value = self.mediator
        context = utils.FakeContext()
        self.servicer.ControllerUnpublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.OK)

    @patch("controller.controller_server.utils.validate_unpublish_volume_request")
    def test_unpublish_volume_validation_exception(self, publish_validation):
        publish_validation.side_effect = [controller_errors.ValidationException("msg")]
        context = utils.FakeContext()
        self.servicer.ControllerUnpublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.INVALID_ARGUMENT)
        self.assertTrue("msg" in context.details)

    def test_unpublish_volume_wrong_volume_id(self):
        self.request.volume_id = "some-wrong-id-format"

        context = utils.FakeContext()
        self.servicer.ControllerUnpublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.INVALID_ARGUMENT)

    def test_unpublish_volume_wrong_node_id(self):
        self.request.node_id = "some-wrong-id-format"

        context = utils.FakeContext()
        self.servicer.ControllerUnpublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.NOT_FOUND)

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    def test_unpublish_volume_get_host_by_host_identifiers_exception(self, enter):
        context = utils.FakeContext()

        self.mediator.get_host_by_host_identifiers = Mock()
        self.mediator.get_host_by_host_identifiers.side_effect = [array_errors.MultipleHostsFoundError("", "")]
        enter.return_value = self.mediator

        self.servicer.ControllerUnpublishVolume(self.request, context)
        self.assertTrue("Multiple hosts" in context.details)
        self.assertEqual(context.code, grpc.StatusCode.INTERNAL)

        self.mediator.get_host_by_host_identifiers.side_effect = [array_errors.HostNotFoundError("")]
        enter.return_value = self.mediator

        self.servicer.ControllerUnpublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.NOT_FOUND)

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    def test_unpublish_volume_unmap_volume_excpetions(self, enter):
        context = utils.FakeContext()

        self.mediator.unmap_volume.side_effect = [array_errors.PermissionDeniedError("msg")]
        enter.return_value = self.mediator
        self.servicer.ControllerUnpublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.PERMISSION_DENIED)

        context = utils.FakeContext()
        self.mediator.unmap_volume.side_effect = [array_errors.VolumeNotFoundError("vol")]
        enter.return_value = self.mediator
        self.servicer.ControllerUnpublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.NOT_FOUND)

        context = utils.FakeContext()
        self.mediator.unmap_volume.side_effect = [array_errors.HostNotFoundError("host")]
        enter.return_value = self.mediator
        self.servicer.ControllerUnpublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.NOT_FOUND)

        context = utils.FakeContext()
        self.mediator.unmap_volume.side_effect = [array_errors.UnMappingError("", "", "")]
        enter.return_value = self.mediator
        self.servicer.ControllerUnpublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.INTERNAL)

        context = utils.FakeContext()
        self.mediator.unmap_volume.side_effect = [array_errors.VolumeAlreadyUnmappedError("")]
        enter.return_value = self.mediator
        self.servicer.ControllerUnpublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.OK)
class TestControllerServerDeleteVolume(unittest.TestCase):

    @patch("controller.array_action.array_mediator_xiv.XIVArrayMediator._connect")
    def setUp(self, connect):
        self.fqdn = "fqdn"
        self.mediator = XIVArrayMediator("user", "password", self.fqdn)
        self.mediator.client = Mock()

        self.mediator.get_volume = Mock()

        self.servicer = ControllerServicer(self.fqdn)

        self.request = Mock()

        self.pool = 'pool1'
        self.request.secrets = {"username": "******", "password": "******", "management_address": "mg"}

        self.request.volume_id = "xiv:vol-id"

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__exit__")
    def test_delete_volume_with_wrong_secrets(self, a_enter, a_exit):
        a_enter.return_value = self.mediator
        context = utils.FakeContext()

        self.request.secrets = {"password": "******", "management_address": "mg"}
        res = self.servicer.DeleteVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.INVALID_ARGUMENT, "username is missing in secrets")
        self.assertTrue("secret" in context.details)

        self.request.secrets = {"username": "******", "management_address": "mg"}
        res = self.servicer.DeleteVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.INVALID_ARGUMENT, "password is missing in secrets")
        self.assertTrue("secret" in context.details)

        self.request.secrets = {"username": "******", "password": "******"}
        res = self.servicer.DeleteVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.INVALID_ARGUMENT, "mgmt address is missing in secrets")
        self.assertTrue("secret" in context.details)

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__exit__")
    def test_delete_volume_invalid_volume_id(self, a_enter, a_exit):
        a_enter.return_value = self.mediator
        context = utils.FakeContext()
        self.request.volume_id = "wrong_id"
        res = self.servicer.DeleteVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.OK)

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__exit__")
    def test_delete_volume_with_array_connection_exception(self, a_enter, a_exit):
        a_enter.side_effect = [Exception("a_enter error")]
        context = utils.FakeContext()
        res = self.servicer.DeleteVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.INTERNAL, "array connection internal error")
        self.assertTrue("a_enter error" in context.details)

    @patch("controller.array_action.array_mediator_xiv.XIVArrayMediator.delete_volume")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    def delete_volume_returns_error(self, a_enter, delete_volume, error, return_code):
        a_enter.return_value = self.mediator
        delete_volume.side_effect = [error]
        context = utils.FakeContext()
        res = self.servicer.DeleteVolume(self.request, context)
        self.assertEqual(context.code, return_code)
        if return_code != grpc.StatusCode.OK:
            msg = str(error)
            self.assertTrue(msg in context.details, "msg : {0} is not in : {1}".format(msg, context.details))

    def test_delete_volume_with_volume_not_found_error(self, ):
        self.delete_volume_returns_error(error=array_errors.VolumeNotFoundError("vol"), return_code=grpc.StatusCode.OK)

    def test_delete_volume_with_delete_volume_other_exception(self):
        self.delete_volume_returns_error(error=Exception("error"), return_code=grpc.StatusCode.INTERNAL)

    @patch("controller.array_action.array_mediator_xiv.XIVArrayMediator.delete_volume")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    def test_delete_volume_succeeds(self, a_enter, delete_volume):
        a_enter.return_value = self.mediator
        context = utils.FakeContext()
        res = self.servicer.DeleteVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.OK)
class TestControllerServerPublishVolume(unittest.TestCase):

    @patch("controller.array_action.array_mediator_xiv.XIVArrayMediator._connect")
    def setUp(self, connect):
        self.fqdn = "fqdn"
        self.hostname = "hostname"
        self.mediator = XIVArrayMediator("user", "password", self.fqdn)
        self.mediator.client = Mock()

        self.mediator.get_host_by_host_identifiers = Mock()
        self.mediator.get_host_by_host_identifiers.return_value = self.hostname, ["iscsi"]

        self.mediator.get_volume_mappings = Mock()
        self.mediator.get_volume_mappings.return_value = {}

        self.mediator.map_volume = Mock()
        self.mediator.map_volume.return_value = 1

        self.mediator.get_array_iqns = Mock()
        self.mediator.get_array_iqns.return_value = "array-iqn"

        self.servicer = ControllerServicer(self.fqdn)

        self.request = Mock()
        arr_type = XIVArrayMediator.array_type
        self.request.volume_id = "{}:wwn1".format(arr_type)
        self.request.node_id = "hostname;iqn.1994-05.com.redhat:686358c930fe;500143802426baf4"
        self.request.readonly = False
        self.request.readonly = False
        self.request.secrets = {"username": "******", "password": "******", "management_address": "mg"}
        self.request.volume_context = {}

        caps = Mock()
        caps.mount = Mock()
        caps.mount.fs_type = "ext4"
        access_types = csi_pb2.VolumeCapability.AccessMode
        caps.access_mode.mode = access_types.SINGLE_NODE_WRITER
        self.request.volume_capability = caps

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    def test_publish_volume_success(self, enter):
        enter.return_value = self.mediator

        context = utils.FakeContext()
        self.servicer.ControllerPublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.OK)

    @patch("controller.controller_server.utils.validate_publish_volume_request")
    def test_publish_volume_validateion_exception(self, publish_validation):
        publish_validation.side_effect = [controller_errors.ValidationException("msg")]
        context = utils.FakeContext()
        self.servicer.ControllerPublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.INVALID_ARGUMENT)
        self.assertTrue("msg" in context.details)

    def test_publish_volume_wrong_volume_id(self):
        self.request.volume_id = "some-wrong-id-format"

        context = utils.FakeContext()
        self.servicer.ControllerPublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.NOT_FOUND)

    def test_publish_volume_wrong_node_id(self):
        self.request.node_id = "some-wrong-id-format"

        context = utils.FakeContext()
        self.servicer.ControllerPublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.NOT_FOUND)

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    def test_publish_volume_get_host_by_host_identifiers_exception(self, enter):
        context = utils.FakeContext()

        self.mediator.get_host_by_host_identifiers = Mock()
        self.mediator.get_host_by_host_identifiers.side_effect = [array_errors.MultipleHostsFoundError("", "")]
        enter.return_value = self.mediator

        self.servicer.ControllerPublishVolume(self.request, context)
        self.assertTrue("Multiple hosts" in context.details)
        self.assertEqual(context.code, grpc.StatusCode.INTERNAL)

        self.mediator.get_host_by_host_identifiers.side_effect = [array_errors.HostNotFoundError("")]
        enter.return_value = self.mediator

        self.servicer.ControllerPublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.NOT_FOUND)

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    def test_publish_volume_get_volume_mappings_one_map_for_existing_host(self, enter):
        context = utils.FakeContext()
        self.mediator.get_volume_mappings = Mock()
        self.mediator.get_volume_mappings.return_value = {self.hostname: 2}
        enter.return_value = self.mediator

        res = self.servicer.ControllerPublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.OK)

        self.assertEqual(res.publish_context["PUBLISH_CONTEXT_LUN"], '2')
        self.assertEqual(res.publish_context["PUBLISH_CONTEXT_CONNECTIVITY"], "iscsi")

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    def test_publish_volume_with_connectivity_type_fc(self, enter):
        context = utils.FakeContext()
        self.mediator.get_host_by_host_identifiers.return_value = self.hostname, ["iscsi", "fc"]
        self.mediator.get_array_fc_wwns = Mock()
        self.mediator.get_array_fc_wwns.return_value = ["500143802426baf4"]
        self.mediator.get_array_iqns = Mock()
        self.mediator.get_array_iqns.return_value = [
            "iqn.1994-05.com.redhat:686358c930fe"]
        enter.return_value = self.mediator

        res = self.servicer.ControllerPublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.OK)

        self.assertEqual(res.publish_context["PUBLISH_CONTEXT_LUN"], '1')
        self.assertEqual(res.publish_context["PUBLISH_CONTEXT_CONNECTIVITY"], "fc")
        self.assertEqual(res.publish_context["PUBLISH_CONTEXT_ARRAY_FC_INITIATORS"], "500143802426baf4")

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    def test_publish_volume_with_connectivity_type_iscsi(self, enter):
        context = utils.FakeContext()
        self.mediator.get_host_by_host_identifiers.return_value = self.hostname, ["iscsi"]
        self.mediator.get_array_iqns = Mock()
        self.mediator.get_array_iqns.return_value = ["iqn.1994-05.com.redhat:686358c930fe"]
        self.mediator.get_array_fc_wwns = Mock()
        self.mediator.get_array_fc_wwns.return_value = ["500143802426baf4"]
        enter.return_value = self.mediator

        res = self.servicer.ControllerPublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.OK)

        self.assertEqual(res.publish_context["PUBLISH_CONTEXT_LUN"], '1')
        self.assertEqual(res.publish_context["PUBLISH_CONTEXT_CONNECTIVITY"],
                         "iscsi")
        self.assertEqual(
            res.publish_context["PUBLISH_CONTEXT_ARRAY_IQN"],
            "iqn.1994-05.com.redhat:686358c930fe")

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    def test_publish_volume_with_node_id_only_has_iqns(self, enter):
        context = utils.FakeContext()
        self.request.node_id = "hostname;iqn.1994-05.com.redhat:686358c930fe;"
        self.mediator.get_host_by_host_identifiers.return_value = self.hostname, ["iscsi"]
        self.mediator.get_array_iqns = Mock()
        self.mediator.get_array_iqns.return_value = [
            "iqn.1994-05.com.redhat:686358c930fe"]
        enter.return_value = self.mediator

        res = self.servicer.ControllerPublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.OK)

        self.assertEqual(res.publish_context["PUBLISH_CONTEXT_LUN"], '1')
        self.assertEqual(res.publish_context["PUBLISH_CONTEXT_CONNECTIVITY"],
                         "iscsi")
        self.assertEqual(
            res.publish_context["PUBLISH_CONTEXT_ARRAY_IQN"],
            "iqn.1994-05.com.redhat:686358c930fe")

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    def test_publish_volume_with_node_id_only_has_wwns(self, enter):
        context = utils.FakeContext()
        self.request.node_id = "hostname;;500143802426baf4"
        self.mediator.get_host_by_host_identifiers.return_value = self.hostname, ["fc"]
        self.mediator.get_array_fc_wwns = Mock()
        self.mediator.get_array_fc_wwns.return_value = ["500143802426baf4"]
        enter.return_value = self.mediator

        res = self.servicer.ControllerPublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.OK)

        self.assertEqual(res.publish_context["PUBLISH_CONTEXT_LUN"], '1')
        self.assertEqual(res.publish_context["PUBLISH_CONTEXT_CONNECTIVITY"],
                         "fc")
        self.assertEqual(
            res.publish_context["PUBLISH_CONTEXT_ARRAY_FC_INITIATORS"],
            "500143802426baf4")

        self.request.node_id = "hostname;;500143802426baf4:500143806626bae2"
        self.mediator.get_host_by_host_identifiers.return_value = self.hostname, ["fc"]
        self.mediator.get_array_fc_wwns = Mock()
        self.mediator.get_array_fc_wwns.return_value = ["500143802426baf4",
                                                        "500143806626bae2"]
        enter.return_value = self.mediator

        res = self.servicer.ControllerPublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.OK)

        self.assertEqual(res.publish_context["PUBLISH_CONTEXT_LUN"], '1')
        self.assertEqual(res.publish_context["PUBLISH_CONTEXT_CONNECTIVITY"],
                         "fc")
        self.assertEqual(
            res.publish_context["PUBLISH_CONTEXT_ARRAY_FC_INITIATORS"],
            "500143802426baf4,500143806626bae2")

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    def test_publish_volume_get_volume_mappings_one_map_for_other_host(self, enter):
        context = utils.FakeContext()
        self.mediator.get_volume_mappings = Mock()
        self.mediator.get_volume_mappings.return_value = {"other-hostname": 3}
        enter.return_value = self.mediator

        self.servicer.ControllerPublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.FAILED_PRECONDITION)
        self.assertTrue("Volume is already mapped" in context.details)

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    def test_publish_volume_get_volume_mappings_more_then_one_mapping(self, enter):
        context = utils.FakeContext()
        self.mediator.get_volume_mappings = Mock()
        self.mediator.get_volume_mappings.return_value = {"other-hostname": 3, self.hostname: 4}
        enter.return_value = self.mediator

        self.servicer.ControllerPublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.FAILED_PRECONDITION)
        self.assertTrue("Volume is already mapped" in context.details)

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    def test_publish_volume_map_volume_excpetions(self, enter):
        context = utils.FakeContext()

        self.mediator.map_volume.side_effect = [array_errors.PermissionDeniedError("msg")]

        enter.return_value = self.mediator
        self.servicer.ControllerPublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.PERMISSION_DENIED)

        self.mediator.map_volume.side_effect = [array_errors.VolumeNotFoundError("vol")]
        enter.return_value = self.mediator
        self.servicer.ControllerPublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.NOT_FOUND)

        self.mediator.map_volume.side_effect = [array_errors.HostNotFoundError("host")]
        enter.return_value = self.mediator
        self.servicer.ControllerPublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.NOT_FOUND)

        self.mediator.map_volume.side_effect = [array_errors.MappingError("", "", "")]
        enter.return_value = self.mediator
        self.servicer.ControllerPublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.INTERNAL)

    @patch.object(XIVArrayMediator, "MAX_LUN_NUMBER", 3)
    @patch.object(XIVArrayMediator, "MIN_LUN_NUMBER", 1)
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    def test_publish_volume_map_volume_lun_already_in_use(self, enter):
        context = utils.FakeContext()

        self.mediator.map_volume.side_effect = [array_errors.LunAlreadyInUseError("", ""), 2]
        self.mediator.map_volume.get_array_iqns.return_value = "array-iqn"
        enter.return_value = self.mediator
        res = self.servicer.ControllerPublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.OK)
        self.assertEqual(res.publish_context["PUBLISH_CONTEXT_LUN"], '2')
        self.assertEqual(res.publish_context["PUBLISH_CONTEXT_CONNECTIVITY"], "iscsi")

        self.mediator.map_volume.side_effect = [
            array_errors.LunAlreadyInUseError("", ""), 2]
        self.mediator.get_host_by_host_identifiers = Mock()
        self.mediator.get_host_by_host_identifiers.return_value = self.hostname, ["fc"]
        self.mediator.get_array_fc_wwns = Mock()
        self.mediator.get_array_fc_wwns.return_value = ["500143802426baf4"]
        enter.return_value = self.mediator
        res = self.servicer.ControllerPublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.OK)
        self.assertEqual(res.publish_context["PUBLISH_CONTEXT_LUN"], '2')
        self.assertEqual(res.publish_context["PUBLISH_CONTEXT_CONNECTIVITY"],
                         "fc")

        self.mediator.map_volume.side_effect = [array_errors.LunAlreadyInUseError("", ""),
                                                array_errors.LunAlreadyInUseError("", ""), 2]
        enter.return_value = self.mediator
        self.servicer.ControllerPublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.OK)
        self.assertEqual(res.publish_context["PUBLISH_CONTEXT_LUN"], '2')
        self.assertEqual(res.publish_context["PUBLISH_CONTEXT_CONNECTIVITY"], "fc")

        self.mediator.map_volume.side_effect = [
            array_errors.LunAlreadyInUseError("", "")] * (self.mediator.max_lun_retries + 1)
        enter.return_value = self.mediator
        self.servicer.ControllerPublishVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.RESOURCE_EXHAUSTED)
class TestControllerServerCreateVolume(unittest.TestCase):

    @patch("controller.array_action.array_mediator_xiv.XIVArrayMediator._connect")
    def setUp(self, connect):
        self.fqdn = "fqdn"
        self.mediator = XIVArrayMediator("user", "password", self.fqdn)
        self.mediator.client = Mock()

        self.mediator.get_volume = Mock()
        self.mediator.get_volume.side_effect = [array_errors.VolumeNotFoundError("vol")]

        self.servicer = ControllerServicer(self.fqdn)

        self.request = Mock()
        caps = Mock()
        caps.mount = Mock()
        caps.mount.fs_type = "ext4"
        access_types = csi_pb2.VolumeCapability.AccessMode
        caps.access_mode.mode = access_types.SINGLE_NODE_WRITER

        self.request.volume_capabilities = [caps]

        self.pool = 'pool1'
        self.request.secrets = {"username": "******", "password": "******", "management_address": "mg"}
        self.request.parameters = {"pool": self.pool}
        self.capacity_bytes = 10
        self.request.capacity_range.required_bytes = self.capacity_bytes
        self.request.name = vol_name

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__exit__")
    def test_create_volume_with_empty_name(self, a_enter, a_exit):
        a_enter.return_value = self.mediator
        self.request.name = ""
        context = utils.FakeContext()
        res = self.servicer.CreateVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.INVALID_ARGUMENT)
        self.assertTrue("name" in context.details)
        self.assertEqual(res, csi_pb2.CreateVolumeResponse())

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.detect_array_type")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__exit__")
    def test_create_volume_succeeds(self, a_exit, a_enter, array_type):
        a_enter.return_value = self.mediator
        context = utils.FakeContext()

        self.mediator.create_volume = Mock()
        self.mediator.create_volume.return_value = utils.get_mock_mediator_response_volume(10, "vol", "wwn", "xiv")
        array_type.return_value = "a9k"
        res = self.servicer.CreateVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.OK)
        self.mediator.get_volume.assert_called_once_with(vol_name)
        self.mediator.create_volume.assert_called_once_with(vol_name, 10, {}, 'pool1')

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.detect_array_type")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__exit__")
    def test_create_volume_with_wrong_secrets(self, a_enter, a_exit, array_type):
        a_enter.return_value = self.mediator
        context = utils.FakeContext()

        self.request.secrets = {"password": "******", "management_address": "mg"}
        self.servicer.CreateVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.INVALID_ARGUMENT, "username is missing in secrets")
        self.assertTrue("secret" in context.details)

        self.request.secrets = {"username": "******", "management_address": "mg"}
        self.servicer.CreateVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.INVALID_ARGUMENT, "password is missing in secrets")
        self.assertTrue("secret" in context.details)

        self.request.secrets = {"username": "******", "password": "******"}
        self.servicer.CreateVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.INVALID_ARGUMENT, "mgmt address is missing in secrets")
        self.assertTrue("secret" in context.details)

        self.request.secrets = []

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.detect_array_type")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__exit__")
    def test_create_volume_with_wrong_parameters(self, a_enter, a_exit, array_type):
        a_enter.return_value = self.mediator
        context = utils.FakeContext()

        self.request.parameters = {"pool": "pool1"}
        res = self.servicer.CreateVolume(self.request, context)
        self.assertNotEqual(context.code, grpc.StatusCode.INVALID_ARGUMENT)

        self.request.parameters = {"capabilities": ""}
        res = self.servicer.CreateVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.INVALID_ARGUMENT, "capacity is missing in secrets")
        self.assertEqual(context.code, grpc.StatusCode.INVALID_ARGUMENT, "pool parameter is missing")
        self.assertTrue("parameter" in context.details)

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__exit__")
    def test_create_volume_with_wrong_volume_capabilities(self, a_enter, a_exit):
        a_enter.return_value = self.mediator
        context = utils.FakeContext()

        caps = Mock()
        caps.mount = Mock()
        caps.mount.fs_type = "ext42"
        access_types = csi_pb2.VolumeCapability.AccessMode
        caps.access_mode.mode = access_types.SINGLE_NODE_WRITER

        self.request.volume_capabilities = [caps]

        res = self.servicer.CreateVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.INVALID_ARGUMENT, "wrong fs_type")
        self.assertTrue("fs_type" in context.details)

        caps.mount.fs_type = "ext4"
        caps.access_mode.mode = access_types.MULTI_NODE_SINGLE_WRITER
        self.request.volume_capabilities = [caps]

        res = self.servicer.CreateVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.INVALID_ARGUMENT, "wrong access_mode")
        self.assertTrue("access mode" in context.details)

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.detect_array_type")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__exit__")
    def test_create_volume_with_array_connection_exception(self, a_enter, a_exit, array_type):
        a_enter.side_effect = [Exception("error")]
        context = utils.FakeContext()
        res = self.servicer.CreateVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.INTERNAL, "connection error occured in array_connection")
        self.assertTrue("error" in context.details)

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.detect_array_type")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__exit__")
    def test_create_volume_with_get_array_type_exception(self, a_enter, a_exit, array_type):
        a_enter.return_value = self.mediator
        context = utils.FakeContext()
        array_type.side_effect = [array_errors.FailedToFindStorageSystemType("endpoint")]
        res = self.servicer.CreateVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.INTERNAL, "failed to find storage system")
        msg = array_errors.FailedToFindStorageSystemType("endpoint").message
        self.assertTrue(msg in context.details)

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.detect_array_type")
    @patch("controller.array_action.array_mediator_xiv.XIVArrayMediator.get_volume")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    def test_create_volume_get_volume_exception(self, a_enter, get_volume, array_type):
        a_enter.return_value = self.mediator
        self.mediator.get_volume.side_effect = [Exception("error")]
        context = utils.FakeContext()
        res = self.servicer.CreateVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.INTERNAL)
        self.assertTrue("error" in context.details)
        self.mediator.get_volume.assert_called_once_with(vol_name)

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.detect_array_type")
    @patch("controller.array_action.array_mediator_xiv.XIVArrayMediator.get_volume")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    def test_create_volume_with_get_volume_illegal_object_name_exception(self, a_enter, get_volume, array_type):
        a_enter.return_value = self.mediator
        self.mediator.get_volume.side_effect = [array_errors.IllegalObjectName("vol")]
        context = utils.FakeContext()
        res = self.servicer.CreateVolume(self.request, context)
        msg = array_errors.IllegalObjectName("vol").message

        self.assertEqual(context.code, grpc.StatusCode.INVALID_ARGUMENT)
        self.assertTrue(msg in context.details)
        self.mediator.get_volume.assert_called_once_with(vol_name)

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.detect_array_type")
    @patch("controller.array_action.array_mediator_xiv.XIVArrayMediator.create_volume")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    def create_volume_returns_error(self, a_enter, create_volume, array_type, return_code, err):
        a_enter.return_value = self.mediator
        create_volume.side_effect = [err]

        context = utils.FakeContext()
        res = self.servicer.CreateVolume(self.request, context)
        msg = str(err)

        self.assertEqual(context.code, return_code)
        self.assertTrue(msg in context.details)
        self.mediator.get_volume.assert_called_once_with(vol_name)
        self.mediator.create_volume.assert_called_once_with(vol_name, self.capacity_bytes, {}, self.pool)

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.detect_array_type")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__exit__")
    def test_create_volume_cuts_name_if_its_too_long(self, a_exit, a_enter, array_type):
        a_enter.return_value = self.mediator
        context = utils.FakeContext()

        self.request.name = "a" * 128
        self.mediator.create_volume = Mock()
        self.mediator.create_volume.return_value = utils.get_mock_mediator_response_volume(10, "vol", "wwn", "xiv")
        array_type.return_value = "a9k"
        res = self.servicer.CreateVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.OK)
        self.mediator.get_volume.assert_called_once_with("a" * self.mediator.max_vol_name_length)

    def test_create_volume_with_illegal_object_name_exception(self):
        self.create_volume_returns_error(return_code=grpc.StatusCode.INVALID_ARGUMENT,
                                         err=array_errors.IllegalObjectName("vol"))

    def test_create_volume_with_create_volume_with_volume_exsits_exception(self):
        self.create_volume_returns_error(return_code=grpc.StatusCode.ALREADY_EXISTS,
                                         err=array_errors.VolumeAlreadyExists("vol", "endpoint"))

    def test_create_volume_with_create_volume_with_pool_does_not_exist_exception(self):
        self.create_volume_returns_error(return_code=grpc.StatusCode.INVALID_ARGUMENT,
                                         err=array_errors.PoolDoesNotExist("pool1", "endpoint"))

    def test_create_volume_with_create_volume_with_pool_does_not_match_capabilities_exception(self):
        self.create_volume_returns_error(return_code=grpc.StatusCode.INVALID_ARGUMENT,
                                         err=array_errors.PoolDoesNotMatchCapabilities("pool1", "", "endpoint"))

    def test_create_volume_with_create_volume_with_capability_not_supported_exception(self):
        self.create_volume_returns_error(return_code=grpc.StatusCode.INVALID_ARGUMENT,
                                         err=array_errors.StorageClassCapabilityNotSupported(["cap"]))

    def test_create_volume_with_create_volume_with_other_exception(self):
        self.create_volume_returns_error(return_code=grpc.StatusCode.INTERNAL,
                                         err=Exception("error"))

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.detect_array_type")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__exit__")
    def test_create_volume_with_name_prefix(self, a_exit, a_enter, array_type):
        a_enter.return_value = self.mediator
        context = utils.FakeContext()

        self.request.name = "some_name"
        self.request.parameters[PARAMETERS_PREFIX] = "prefix"
        self.mediator.create_volume = Mock()
        self.mediator.create_volume.return_value = utils.get_mock_mediator_response_volume(10, "vol", "wwn", "xiv")
        array_type.return_value = "a9k"
        res = self.servicer.CreateVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.OK)
        self.mediator.create_volume.assert_called_once_with("prefix_some_name", 10, {}, "pool1")

    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.detect_array_type")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__enter__")
    @patch("controller.array_action.array_connection_manager.ArrayConnectionManager.__exit__")
    def test_create_volume_with_zero_size(self, a_exit, a_enter, array_type):
        a_enter.return_value = self.mediator
        context = utils.FakeContext()

        self.request.capacity_range.required_bytes = 0
        self.mediator.create_volume = Mock()
        self.mediator.create_volume.return_value = utils.get_mock_mediator_response_volume(10, "vol", "wwn", "xiv")
        array_type.return_value = "a9k"
        res = self.servicer.CreateVolume(self.request, context)
        self.assertEqual(context.code, grpc.StatusCode.OK)
        self.mediator.create_volume.assert_called_once_with(self.request.name, 1 * 1024 * 1024 * 1024, {}, "pool1")