# Copyright (c) 2015 EMC Corporation.
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

from unittest import mock

from oslo_utils import units

from manila.common import constants as const
from manila.share import configuration as conf
from manila.share.drivers.dell_emc.common.enas import utils
from manila.tests import fake_share


def query(func):
    def inner(*args, **kwargs):
        return (
            '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
            '<RequestPacket xmlns="http://www.emc.com/schemas/celerra/'
            'xml_api"><Request><Query>'
            + func(*args, **kwargs)
            + '</Query></Request></RequestPacket>'
        )

    return inner


def start_task(func):
    def inner(*args, **kwargs):
        return (
            '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
            '<RequestPacket xmlns="http://www.emc.com/schemas/celerra/'
            'xml_api"><Request><StartTask timeout="300">'
            + func(*args, **kwargs)
            + '</StartTask></Request></RequestPacket>')

    return inner


def response(func):
    def inner(*args, **kwargs):
        return (
            '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
            '<ResponsePacket xmlns="http://www.emc.com/schemas/celerra/'
            'xml_api"><Response>'
            + func(*args, **kwargs)
            + '</Response></ResponsePacket>'
        ).encode()

    return inner


class FakeData(object):
    # Share information
    share_id = '7cf7c200_d3af_4e05_b87e_9167c95df4f9'
    host = 'HostA@BackendB#fake_pool_name'
    share_name = share_id
    share_size = 10
    new_size = 20
    src_share_name = '7cf7c200_d3af_4e05_b87e_9167c95df4f0'

    # Snapshot information
    snapshot_name = 'de4c9050-e2f9-4ce1-ade4-5ed0c9f26451'
    src_snap_name = 'de4c9050-e2f9-4ce1-ade4-5ed0c9f26452'
    snapshot_id = 'fake_snap_id'
    snapshot_size = 10 * units.Ki

    # Share network information
    share_network_id = 'c5b3a865-56d0-4d88-abe5-879965e099c9'
    cidr = '192.168.1.0/24'
    cidr_v6 = 'fdf8:f53b:82e1::/64'
    segmentation_id = 100
    network_allocations_id1 = '132dbb10-9a36-46f2-8d89-3d909830c356'
    network_allocations_id2 = '7eabdeed-bad2-46ea-bd0f-a33884c869e0'
    network_allocations_id3 = '98c9e490-a842-4e59-b59a-a6042069d35b'
    network_allocations_id4 = '6319a917-ab95-4b65-a498-773ae33c5550'
    network_allocations_ip1 = '192.168.1.1'
    network_allocations_ip2 = '192.168.1.2'
    network_allocations_ip3 = 'fdf8:f53b:82e1::1'
    network_allocations_ip4 = 'fdf8:f53b:82e1::2'

    network_allocations_ip_version1 = 4
    network_allocations_ip_version2 = 4
    network_allocations_ip_version3 = 6
    network_allocations_ip_version4 = 6
    domain_name = 'fake_domain'
    domain_user = 'administrator'
    domain_password = 'password'
    dns_ip_address = '192.168.1.200'
    dns_ipv6_address = 'fdf8:f53b:82e1::f'

    # Share server information
    share_server_id = '56aafd02-4d44-43d7-b784-57fc88167224'

    # Filesystem information
    filesystem_name = share_name
    filesystem_id = 'fake_filesystem_id'
    filesystem_size = 10 * units.Ki
    filesystem_new_size = 20 * units.Ki

    # Mountpoint information
    path = '/' + share_name

    # Mover information
    mover_name = 'server_2'
    mover_id = 'fake_mover_id'
    interface_name1 = network_allocations_id1[-12:]
    interface_name2 = network_allocations_id2[-12:]
    interface_name3 = network_allocations_id3[-12:]
    interface_name4 = network_allocations_id4[-12:]
    long_interface_name = network_allocations_id1
    net_mask = '255.255.255.0'
    net_mask_v6 = 64
    device_name = 'cge-1-0'
    interconnect_id = '2001'

    # VDM information
    vdm_name = share_server_id
    vdm_id = 'fake_vdm_id'

    # Pool information
    pool_name = 'fake_pool_name'
    pool_id = 'fake_pool_id'
    pool_used_size = 20480
    pool_total_size = 511999

    # NFS share access information
    rw_hosts = ['192.168.1.1', '192.168.1.2']
    ro_hosts = ['192.168.1.3', '192.168.1.4']
    nfs_host_ip = '192.168.1.5'
    rw_hosts_ipv6 = ['fdf8:f53b:82e1::1', 'fdf8:f53b:82e1::2']
    ro_hosts_ipv6 = ['fdf8:f53b:82e1::3', 'fdf8:f53b:82e1::4']
    nfs_host_ipv6 = 'fdf8:f53b:82e1::5'

    fake_output = ''

    fake_error_msg = 'fake error message'

    emc_share_backend = 'vnx'
    powermax_share_backend = 'powermax'
    emc_nas_server = '192.168.1.20'
    emc_nas_login = 'fakename'
    emc_nas_password = 'fakepassword'
    share_backend_name = 'EMC_NAS_Storage'

    cifs_access = """
        1478607389: SMB:11: Unix user 'Guest' UID=32769
        1478607389: SMB:10: FindUserUid:Access_Password 'Guest',1=0x8001 T=0
        1478607389: SHARE: 6: ALLOWED:fullcontrol:S-1-5-15-3399d125-6dcdf5f4
        1478607389: SMB:11: Unix user 'Administrator' UID=32768
        1478607389: SMB:10: FindUserUid:Access_Password 'Administrator',
        1478607389: SHARE: 6: ALLOWED:fullcontrol:S-1-5-15-3399d125
        """


class StorageObjectTestData(object):
    def __init__(self):
        self.share_name = FakeData.share_name

        self.filesystem_name = FakeData.filesystem_name
        self.filesystem_id = FakeData.filesystem_id
        self.filesystem_size = 10 * units.Ki
        self.filesystem_new_size = 20 * units.Ki

        self.path = FakeData.path

        self.snapshot_name = FakeData.snapshot_name
        self.snapshot_id = FakeData.snapshot_id
        self.snapshot_size = 10 * units.Ki

        self.src_snap_name = FakeData.src_snap_name
        self.src_fileystems_name = FakeData.src_share_name

        self.mover_name = FakeData.mover_name
        self.mover_id = FakeData.mover_id
        self.vdm_name = FakeData.vdm_name
        self.vdm_id = FakeData.vdm_id

        self.pool_name = FakeData.pool_name
        self.pool_id = FakeData.pool_id
        self.pool_used_size = FakeData.pool_used_size
        self.pool_total_size = FakeData.pool_total_size

        self.interface_name1 = FakeData.interface_name1
        self.interface_name2 = FakeData.interface_name2
        self.interface_name3 = FakeData.interface_name3
        self.interface_name4 = FakeData.interface_name4
        self.long_interface_name = FakeData.long_interface_name
        self.ip_address1 = FakeData.network_allocations_ip1
        self.ip_address2 = FakeData.network_allocations_ip2
        self.ip_address3 = FakeData.network_allocations_ip3
        self.ip_address4 = FakeData.network_allocations_ip4
        self.net_mask = FakeData.net_mask
        self.net_mask_v6 = FakeData.net_mask_v6
        self.vlan_id = FakeData.segmentation_id

        self.cifs_server_name = FakeData.vdm_name

        self.domain_name = FakeData.domain_name
        self.domain_user = FakeData.domain_user
        self.domain_password = FakeData.domain_password
        self.dns_ip_address = FakeData.dns_ip_address

        self.device_name = FakeData.device_name

        self.interconnect_id = FakeData.interconnect_id

        self.rw_hosts = FakeData.rw_hosts
        self.ro_hosts = FakeData.ro_hosts
        self.nfs_host_ip = FakeData.nfs_host_ip

        self.rw_hosts_ipv6 = FakeData.rw_hosts_ipv6
        self.ro_hosts_ipv6 = FakeData.ro_hosts_ipv6
        self.nfs_host_ipv6 = FakeData.nfs_host_ipv6

        self.fake_output = FakeData.fake_output

    @response
    def resp_get_error(self):
        return (
            '<QueryStatus maxSeverity="error">'
            '<Problem messageCode="18522112101" facility="Generic" '
            'component="API" message="Fake message." severity="error">'
            '<Description>Fake description.</Description>'
            '<Action>Fake action.</Action>'
            '<Diagnostics>Fake diagnostics.</Diagnostics>'
            '</Problem>'
            '<Problem messageCode="18522112101" facility="Generic" '
            'component="API" message="Fake message." severity="error">'
            '<Description>Fake description.</Description>'
            '<Action>Fake action.</Action>'
            '<Diagnostics>Fake diagnostics.</Diagnostics>'
            '</Problem>'
            '</QueryStatus> '
        )

    @response
    def resp_get_without_value(self):
        return (
            '<QueryStatus maxSeverity="ok"/>'
        )

    @response
    def resp_task_succeed(self):
        return (
            '<TaskResponse taskId="123">'
            '<Status maxSeverity="ok"/>'
            '</TaskResponse>'
        )

    @response
    def resp_task_error(self):
        return (
            '<TaskResponse taskId="123">'
            '<Status maxSeverity="error"/>'
            '</TaskResponse>'
        )

    @response
    def resp_invalid_mover_id(self):
        return (
            '<Fault maxSeverity="error">'
            '<Problem messageCode="14227341323" facility="Prevalidator" '
            'component="API" message="Mover with id=100 not found." '
            'severity="error">'
            '<Description>The Mover ID supplied with the request is invalid.'
            '</Description>'
            '<Action>Refer to the XML API v2 schema/documentation and correct '
            'your user program logic.</Action>'
            '<Diagnostics> Exception tag: 14fb692e556 Exception '
            'message: com.emc.nas.ccmd.common.MessageInstanceImpl@5004000d '
            '</Diagnostics>'
            '</Problem>'
            '</Fault> '
        )

    @response
    def resp_need_retry(self):
        return ('<TaskResponse taskId="915525">'
                '<Status maxSeverity = "error">'
                '<Problem messageCode = "13421840537" component = "fake"'
                '    message = "unable to acquire lock(s), try later"'
                '    severity = "error" >'
                '<Description> fake desp. </Description>'
                '<Action>fake action </Action>'
                '</Problem></Status></TaskResponse>')

    @start_task
    def req_fake_start_task(self):
        return '<StartFake name="foo"></StartFake>'


class FileSystemTestData(StorageObjectTestData):
    def __init__(self):
        super(FileSystemTestData, self).__init__()

    @start_task
    def req_create_on_vdm(self):
        return (
            '<NewFileSystem name="%(name)s">'
            '<Vdm vdm="%(id)s"/>'
            '<StoragePool mayContainSlices="true" pool="%(pool_id)s" '
            'size="%(size)s"/>'
            '</NewFileSystem>'
            % {'name': self.filesystem_name,
               'id': self.vdm_id,
               'pool_id': self.pool_id,
               'size': self.filesystem_size}
        )

    @start_task
    def req_create_on_mover(self):
        return (
            '<NewFileSystem name="%(name)s">'
            '<Mover mover="%(id)s"/>'
            '<StoragePool mayContainSlices="true" pool="%(pool_id)s" '
            'size="%(size)s"/>'
            '</NewFileSystem>'
            % {'name': self.filesystem_name,
               'id': self.mover_id,
               'pool_id': self.pool_id,
               'size': self.filesystem_size}
        )

    @response
    def resp_create_but_already_exist(self):
        return (
            ' <TaskResponse taskId="31362">'
            '<Status maxSeverity="error">'
            '<Problem messageCode="13691191325" component="APL" '
            'message="A file system with the name fake_filesystem '
            'already exists." severity="error">'
            '<Description></Description>'
            '<Action></Action>'
            '</Problem>'
            '</Status>'
            '</TaskResponse> '
        )

    @start_task
    def req_delete(self):
        return (
            '<DeleteFileSystem fileSystem="%(id)s"/>' %
            {'id': self.filesystem_id}
        )

    @response
    def resp_delete_but_failed(self):
        return (
            '<Fault maxSeverity="error">'
            '<Problem messageCode="14227341326" facility="Prevalidator" '
            'component="API" message="File system with id=77777 not found." '
            'severity="error">'
            '<Description>The file system ID supplied with the request is '
            'invalid.</Description>'
            '<Action>Refer to the XML API v2 schema/documentation and correct '
            'your user program logic.</Action>'
            '<Diagnostics> Exception tag: 14fb6b6a7b8 Exception '
            'message: com.emc.nas.ccmd.common.MessageInstanceImpl@5004000e '
            '</Diagnostics>'
            '</Problem>'
            '</Fault> '
        )

    @start_task
    def req_extend(self):
        return (
            '<ExtendFileSystem fileSystem="%(id)s">'
            '<StoragePool pool="%(pool_id)s" size="%(size)d"/>'
            '</ExtendFileSystem>' %
            {'id': self.filesystem_id,
             'pool_id': self.pool_id,
             'size': self.filesystem_new_size - self.filesystem_size}
        )

    @response
    def resp_extend_but_error(self):
        return (
            '<Fault maxSeverity="error">'
            '<Problem messageCode="14227341325" facility="Prevalidator" '
            'component="API" message="Fake message.">'
            '<Description>Fake description.</Description>'
            '<Action>Fake action.</Action>'
            '<Diagnostics> Fake diagnostics.</Diagnostics>'
            '</Problem>'
            '</Fault> '
        )

    @query
    def req_get(self):
        return (
            '<FileSystemQueryParams>'
            '<AspectSelection fileSystemCapacityInfos="true" '
            'fileSystems="true"/>'
            '<Alias name="%(name)s"/>'
            '</FileSystemQueryParams>' %
            {'name': self.filesystem_name}
        )

    @response
    def resp_get_succeed(self):
        return (
            '<QueryStatus maxSeverity="ok"/>'
            '<FileSystem name="%(name)s" type="uxfs" volume="107" '
            'storagePools="%(pool_id)s" storages="1" containsSlices="true" '
            'internalUse="false" dataServicePolicies="Thin=No,Compressed=No,'
            'Mirrored=No,Tiering policy=Auto-Tier/Highest Available Tier" '
            'fileSystem="%(id)s">'
            '<ProductionFileSystemData cwormState="off"/>'
            '</FileSystem>'
            '<FileSystemCapacityInfo volumeSize="%(size)s" '
            'fileSystem="%(id)s"/>' %
            {'name': self.filesystem_name,
             'id': self.filesystem_id,
             'size': self.filesystem_size,
             'pool_id': self.pool_id}
        )

    @response
    def resp_get_but_miss_property(self):
        return (
            '<QueryStatus maxSeverity="ok"/>'
            '<FileSystem name="%(name)s" type="uxfs" volume="107" '
            'storagePools="%(pool_id)s" storages="1" containsSlices="true" '
            'internalUse="false" '
            'fileSystem="%(id)s">'
            '<ProductionFileSystemData cwormState="off"/>'
            '</FileSystem>'
            '<FileSystemCapacityInfo volumeSize="%(size)s" '
            'fileSystem="%(id)s"/>' %
            {'name': self.filesystem_name,
             'id': self.filesystem_id,
             'size': self.filesystem_size,
             'pool_id': self.pool_id}
        )

    @response
    def resp_get_but_not_found(self):
        return (
            '<QueryStatus maxSeverity="warning">'
            '<Problem messageCode="18522112101" facility="Generic" '
            'component="API" message="The query may be incomplete or '
            'requested object not found." severity="warning">'
            '<Description>The query may be incomplete because some of the '
            'Celerra components are unavailable or do not exist. Another '
            'reason may be application error. </Description>'
            '<Action>If the entire Celerra is functioning correctly, '
            'check your client application logic. </Action>'
            '<Diagnostics>File system not found.</Diagnostics>'
            '</Problem>'
            '<Problem messageCode="18522112101" facility="Generic" '
            'component="API" message="The query may be incomplete or '
            'requested object not found." severity="warning">'
            '<Description>The query may be incomplete because some of the '
            'Celerra components are unavailable or do not exist. Another '
            'reason may be application error.</Description>'
            '<Action>If the entire Celerra is functioning correctly, '
            'check your client application logic.</Action>'
            '<Diagnostics>Migration file system not found.</Diagnostics>'
            '</Problem>'
            '</QueryStatus> '
        )

    def cmd_create_from_ckpt(self):
        return [
            'env', 'NAS_DB=/nas', '/nas/bin/nas_fs',
            '-name', self.filesystem_name,
            '-type', 'uxfs',
            '-create',
            'samesize=' + self.src_fileystems_name,
            'pool=' + self.pool_name,
            'storage=SINGLE',
            'worm=off',
            '-thin', 'no',
            '-option', 'slice=y',
        ]

    def cmd_copy_ckpt(self):
        session_name = self.filesystem_name + ':' + self.src_snap_name

        return [
            'env', 'NAS_DB=/nas', '/nas/bin/nas_copy',
            '-name', session_name[0:63],
            '-source', '-ckpt', self.src_snap_name,
            '-destination', '-fs', self.filesystem_name,
            '-interconnect', "id=" + self.interconnect_id,
            '-overwrite_destination',
            '-full_copy',
        ]

    output_copy_ckpt = "OK"
    error_copy_ckpt = "ERROR"

    def cmd_nas_fs_info(self):
        return [
            'env', 'NAS_DB=/nas', '/nas/bin/nas_fs',
            '-info', self.filesystem_name,
        ]

    def output_info(self):
        return (
            """output = id        = 515
                name      = %(share_name)s
                acl       = 0
                in_use    = True
                type      = uxfs
                worm      = off
                volume    = v993
                deduplication   = Off
                thin_storage    = True
                tiering_policy  = Auto-Tier/Optimize Pool
                compressed= False
                mirrored  = False
                ckpts     = %(ckpt)s
                stor_devs = FNM00124500890-004B
                disks     = d7
                 disk=d7    fakeinfo""" %
            {'share_name': self.filesystem_name,
             'ckpt': self.snapshot_name})

    def cmd_delete(self):
        return [
            'env', 'NAS_DB=/nas', '/nas/bin/nas_fs',
            '-delete', self.snapshot_name,
            '-Force',
        ]


class SnapshotTestData(StorageObjectTestData):
    def __init__(self):
        super(SnapshotTestData, self).__init__()

    @start_task
    def req_create(self):
        return (
            '<NewCheckpoint checkpointOf="%(fsid)s" '
            'name="%(name)s"><SpaceAllocationMethod>'
            '<StoragePool pool="%(pool_id)s"/></SpaceAllocationMethod>'
            '</NewCheckpoint>'
            % {'fsid': self.filesystem_id,
               'name': self.snapshot_name,
               'pool_id': self.pool_id}
        )

    @start_task
    def req_create_with_size(self):
        return (
            '<NewCheckpoint checkpointOf="%(fsid)s" '
            'name="%(name)s"><SpaceAllocationMethod>'
            '<StoragePool pool="%(pool_id)s" size="%(size)s"/>'
            '</SpaceAllocationMethod>'
            '</NewCheckpoint>'
            % {'fsid': self.filesystem_id,
               'name': self.snapshot_name,
               'pool_id': self.pool_id,
               'size': self.snapshot_size}
        )

    @response
    def resp_create_but_already_exist(self):
        return (
            '<Status maxSeverity="error">'
            '<Problem messageCode="13690535947" component="APL" '
            'message="snap_0 is already in use." severity="error">'
            '<Description></Description>'
            '<Action></Action>'
            '</Problem>'
            '</Status>'
        )

    @query
    def req_get(self):
        return (
            '<CheckpointQueryParams><Alias name="%(name)s"/>'
            '</CheckpointQueryParams>'
            % {'name': self.snapshot_name}
        )

    @response
    def resp_get_succeed(self):
        return (
            '<QueryStatus maxSeverity="ok"/>'
            '<Checkpoint checkpointOf="%(fs_id)s" name="%(name)s_replica1"'
            ' state="active" time="1405428355" fileSystemSize="0"'
            ' checkpoint="%(snap_id)s"/>'
            % {'name': self.snapshot_name,
               'fs_id': self.filesystem_id,
               'snap_id': self.snapshot_id}
        )

    @start_task
    def req_delete(self):
        return (
            '<DeleteCheckpoint checkpoint="%(id)s"/>' %
            {'id': self.snapshot_id}
        )


class MountPointTestData(StorageObjectTestData):
    def __init__(self):
        super(MountPointTestData, self).__init__()

    @start_task
    def req_create(self, mover_id, is_vdm=True):
        return (
            '<NewMount path="%(path)s" fileSystem="%(fs_id)s">'
            '<MoverOrVdm mover="%(mover_id)s" moverIdIsVdm="%(is_vdm)s"/>'
            '</NewMount>' %
            {'path': self.path,
             'fs_id': self.filesystem_id,
             'mover_id': mover_id,
             'is_vdm': 'true' if is_vdm else 'false'}
        )

    @response
    def resp_create_but_already_exist(self):
        return (
            '<TaskResponse taskId="31428">'
            '<Status maxSeverity="error">'
            '<Problem messageCode="13690601492" component="APL" '
            'message="Mount already exists" severity="error">'
            '<Description></Description> <Action></Action>'
            '</Problem>'
            '</Status>'
            '</TaskResponse> ')

    @start_task
    def req_delete(self, mover_id, is_vdm=True):
        return (
            '<DeleteMount path="%(path)s" mover="%(mover_id)s" '
            'moverIdIsVdm="%(is_vdm)s"/>' %
            {'path': self.path,
             'mover_id': mover_id,
             'is_vdm': 'true' if is_vdm else 'false'}
        )

    @response
    def resp_delete_but_nonexistent(self):
        return (
            '<TaskResponse taskId="31401">'
            '<Status maxSeverity="error"> <Problem messageCode="13690601492" '
            'component="APL" message="/fake_filesystem : No such path or '
            'invalid operation." severity="error">'
            '<Description></Description> <Action></Action>'
            '</Problem>'
            '</Status>'
            '</TaskResponse> '
        )

    @query
    def req_get(self, mover_id, is_vdm=True):
        return (
            '<MountQueryParams><MoverOrVdm mover="%(mover_id)s" '
            'moverIdIsVdm="%(is_vdm)s"/></MountQueryParams>' %
            {'mover_id': mover_id,
             'is_vdm': 'true' if is_vdm else 'false'}
        )

    @response
    def resp_get_succeed(self, mover_id, is_vdm=True):
        return (
            '<QueryStatus maxSeverity="ok"/>'
            '<Mount fileSystem="%(fsID)s" disabled="false"'
            ' ntCredential="false" path="%(path)s" mover="%(mover_id)s"'
            ' moverIdIsVdm="%(is_vdm)s">'
            '<NfsOptions ro="false" virusScan="true"'
            ' prefetch="true" uncached="false"/>'
            '<CifsOptions cifsSyncwrite="false" notify="true"'
            ' triggerLevel="512" notifyOnAccess="false"'
            ' notifyOnWrite="false" oplock="true" accessPolicy="NATIVE"'
            ' lockingPolicy="nolock"/></Mount>'
            % {'path': self.path,
               'fsID': self.filesystem_id,
               'mover_id': mover_id,
               'is_vdm': 'true' if is_vdm else 'false'}
        )

    def cmd_server_mount(self, mode):
        return [
            'env', 'NAS_DB=/nas', '/nas/bin/server_mount', self.vdm_name,
            '-option', mode,
            self.filesystem_name,
            self.path,
        ]

    def cmd_server_umount(self):
        return [
            'env', 'NAS_DB=/nas', '/nas/bin/server_umount', self.vdm_name,
            '-perm', self.snapshot_name,
        ]


class VDMTestData(StorageObjectTestData):
    def __init__(self):
        super(VDMTestData, self).__init__()

    @start_task
    def req_create(self):
        return (
            '<NewVdm mover="%(mover_id)s" name="%(vdm_name)s"/>' %
            {'mover_id': self.mover_id, 'vdm_name': self.vdm_name}
        )

    @response
    def resp_create_but_already_exist(self):
        return (
            '<TaskResponse taskId="32551">'
            '<Status maxSeverity="error">'
            '<Problem messageCode="13421840550" component="CS_CORE" '
            'message="VDM_01 : an entry with this name already exists" '
            'severity="error">'
            '<Description>Duplicate name specified</Description>'
            '<Action>Specify a unqiue name</Action>'
            '</Problem>'
            '<Problem messageCode="13421840550" component="CS_CORE" '
            'message="VDM_01 : an entry with this name already exists" '
            'severity="error">'
            '<Description>Duplicate name specified</Description>'
            '<Action>Specify a unqiue name</Action>'
            '</Problem>'
            '</Status>'
            '</TaskResponse> '
        )

    @query
    def req_get(self):
        return '<VdmQueryParams/>'

    @response
    def resp_get_succeed(self, name=None, interface1=None, interface2=None):
        if name is None:
            name = self.vdm_name

        if interface1 is None:
            interface1 = self.interface_name1

        if interface2 is None:
            interface2 = self.interface_name2

        return (
            '<QueryStatus maxSeverity="ok"/>'
            '<Vdm name="%(vdm_name)s" state="loaded" mover="%(mover_id)s" '
            'rootFileSystem="396" vdm="%(vdm_id)s">'
            '<Status maxSeverity="ok"/>'
            '<Interfaces> <li>%(interface1)s</li> <li>%(interface2)s</li>'
            '</Interfaces> </Vdm>' %
            {'vdm_name': name,
             'vdm_id': self.vdm_id,
             'mover_id': self.mover_id,
             'interface1': interface1,
             'interface2': interface2}
        )

    @response
    def resp_get_but_not_found(self):
        return (
            '<QueryStatus maxSeverity="ok"/>'
        )

    @start_task
    def req_delete(self):
        return '<DeleteVdm vdm="%(vdmid)s"/>' % {'vdmid': self.vdm_id}

    def cmd_attach_nfs_interface(self, interface=None):
        if interface is None:
            interface = self.interface_name2

        return [
            'env', 'NAS_DB=/nas', '/nas/bin/nas_server',
            '-vdm', self.vdm_name,
            '-attach', interface,
        ]

    def cmd_detach_nfs_interface(self):
        return [
            'env', 'NAS_DB=/nas', '/nas/bin/nas_server',
            '-vdm', self.vdm_name,
            '-detach', self.interface_name2,
        ]

    def cmd_get_interfaces(self):
        return [
            'env', 'NAS_DB=/nas', '/nas/bin/nas_server',
            '-i',
            '-vdm', self.vdm_name,
        ]

    def output_get_interfaces_vdm(self,
                                  cifs_interface=FakeData.interface_name1,
                                  nfs_interface=FakeData.interface_name2):
        return (
            """id        = %(vdmid)s
            name      = %(name)s
            acl       = 0
            type      = vdm
            server    = server_2
            rootfs    = root_fs_vdm_vdm-fakeid
            I18N mode = UNICODE
            mountedfs =
            member_of =
            status    :
              defined = enabled
               actual = loaded, active
            Interfaces to services mapping:
             interface=%(nfs_if_name)s :vdm
             interface=%(cifs_if_name)s :cifs""" %
            {'vdmid': self.vdm_id,
             'name': self.vdm_name,
             'nfs_if_name': nfs_interface,
             'cifs_if_name': cifs_interface}
        )

    def output_get_interfaces_nfs(self,
                                  cifs_interface=FakeData.interface_name1,
                                  nfs_interface=FakeData.interface_name2):
        return (
            """id        = %(vdmid)s
            name      = %(name)s
            acl       = 0
            type      = vdm
            server    = server_2
            rootfs    = root_fs_vdm_vdm-fakeid
            I18N mode = UNICODE
            mountedfs =
            member_of =
            status    :
              defined = enabled
               actual = loaded, active
            Interfaces to services mapping:
             interface=%(nfs_if_name)s :nfs
             interface=%(cifs_if_name)s :cifs""" %
            {'vdmid': self.vdm_id,
             'name': self.vdm_name,
             'nfs_if_name': nfs_interface,
             'cifs_if_name': cifs_interface}
        )


class PoolTestData(StorageObjectTestData):
    def __init__(self):
        super(PoolTestData, self).__init__()

    @query
    def req_get(self):
        return (
            '<StoragePoolQueryParams/>'
        )

    @response
    def resp_get_succeed(self, name=None, id=None):
        if not name:
            name = self.pool_name
        if not id:
            id = self.pool_id
        return (
            '<QueryStatus maxSeverity="ok"/>'
            '<StoragePool movers="1 2" memberVolumes="98" storageSystems="1" '
            'name="fake" '
            'description="Mapped Pool Pool_2 on APM00152904560" '
            'mayContainSlicesDefault="true" diskType="Capacity" '
            'size="511999" usedSize="20480" autoSize="511999" '
            'virtualProvisioning="false" isHomogeneous="true" '
            'dataServicePolicies="Thin=No,Compressed=No,Mirrored=No,Tiering '
            'policy=Auto-Tier/Highest Available Tier" templatePool="59" '
            'stripeCount="5" stripeSize="256" pool="9">'
            '<SystemStoragePoolData dynamic="true" greedy="true" '
            'potentialAdditionalSize="0" isBackendPool="true"/>'
            '</StoragePool>'
            '<StoragePool movers="1 2" memberVolumes="98" storageSystems="1" '
            'name="%(name)s" '
            'description="Mapped Pool Pool_2 on APM00152904560" '
            'mayContainSlicesDefault="true" diskType="Capacity" '
            'size="411999" usedSize="%(pool_used_size)s" '
            'autoSize="%(pool_total_size)s" virtualProvisioning="false" '
            'isHomogeneous="true" '
            'dataServicePolicies="Thin=No,Compressed=No,Mirrored=No,Tiering '
            'policy=Auto-Tier/Highest Available Tier" templatePool="59" '
            'stripeCount="5" stripeSize="256" pool="%(id)s">'
            '<SystemStoragePoolData dynamic="true" greedy="true" '
            'potentialAdditionalSize="0" isBackendPool="true"/>'
            '</StoragePool>' %
            {'name': name,
             'id': id,
             'pool_used_size': self.pool_used_size,
             'pool_total_size': self.pool_total_size}
        )


class MoverTestData(StorageObjectTestData):
    def __init__(self):
        super(MoverTestData, self).__init__()

    @query
    def req_get_ref(self):
        return (
            '<MoverQueryParams>'
            '<AspectSelection movers="true"/>'
            '</MoverQueryParams>'
        )

    @response
    def resp_get_ref_succeed(self, name=None):
        if not name:
            name = self.mover_name
        return (
            '<QueryStatus maxSeverity="info">'
            '<Problem messageCode="18522112101" facility="Generic" '
            'component="API" message="The query may be incomplete or '
            'requested object not found." severity="warning">'
            '<Description>The query may be incomplete because some of the '
            'Celerra components are unavailable or do not exist. Another '
            'reason may be application error.</Description>'
            '<Action>If the entire Celerra is functioning correctly, '
            'check your client application logic.</Action>'
            '<Diagnostics>Standby Data Mover server_2.faulted.server_3 is '
            'out of service.</Diagnostics>'
            '</Problem>'
            '</QueryStatus>'
            '<Mover name="%(name)s" host="1" role="primary" standbys="2" '
            'i18NMode="UNICODE" failoverPolicy="auto" '
            'ntpServers="192.168.1.82" mover="%(id)s"/>'
            '<Mover name="server_3" host="2" role="standby" standbyFors="1" '
            'i18NMode="ASCII" failoverPolicy="none" mover="2"/>' %
            {'name': name, 'id': self.mover_id}
        )

    @query
    def req_get(self):
        return (
            '<MoverQueryParams mover="%(id)s">'
            '<AspectSelection moverInterfaces="true" moverStatuses="true" '
            'movers="true" moverNisDomains="true" moverNetworkDevices="true" '
            'moverDnsDomains="true" moverRoutes="true" '
            'moverDeduplicationSettings="true"/>'
            '</MoverQueryParams>' %
            {'id': self.mover_id}
        )

    @response
    def resp_get_succeed(self, name=None):
        if not name:
            name = self.mover_name
        return (
            '<QueryStatus maxSeverity="ok"/><Mover name="%(name)s" '
            'host="1" role="primary" i18NMode="UNICODE" failoverPolicy="none"'
            ' ntpServers="192.168.1.82" mover="%(id)s"/>'
            '<MoverStatus version="T8.1.3.34944" csTime="1406795150" '
            'clock="140681" timezone="GMT-5" uptime="85096" '
            'mover="%(id)s"><Status maxSeverity="ok"/>'
            '</MoverStatus>'
            '<MoverDnsDomain servers="192.168.1.82" protocol="udp" '
            'mover="%(id)s" name="win2012.openstack"/>'
            '<MoverInterface name="%(long_interface_name)s" device="mge0" '
            'ipVersion="IPv4" netMask="255.255.255.0" '
            'broadcastAddr="128.221.252.255" '
            'macAddr="0:60:16:53:cc:87" mtu="1500" up="true" vlanid="0" '
            'mover="%(id)s" ipAddress="128.221.252.1"/>'
            '<MoverInterface name="%(interface_name1)s" device="cge-2-0" '
            'ipVersion="IPv4" netMask="255.255.255.0" '
            'broadcastAddr="128.221.252.255" macAddr="0:60:16:53:cc:87" '
            'mtu="1500" up="true" vlanid="0" mover="%(id)s" '
            'ipAddress="128.221.252.2"/>'
            '<MoverInterface name="%(interface_name2)s" device="cge-2-1" '
            'ipVersion="IPv4" netMask="255.255.255.0" '
            'broadcastAddr="128.221.252.255" macAddr="0:60:16:53:cc:87" '
            'mtu="1500" up="true" vlanid="0" mover="%(id)s" '
            'ipAddress="128.221.252.3"/>'
            '<MoverRoute destination="0.0.0.0" interface="192.168.1.178" '
            'ipVersion="IPv4" netMask="0.0.0.0" '
            'gateway="192.168.1.217" mover="%(id)s"/>'
            '<LogicalNetworkDevice speed="auto" interfaces="192.168.1.136" '
            'type="physical-ethernet" mover="%(id)s" name="cge-2-0"/>'
            % {'id': self.mover_id,
               'name': name,
               'long_interface_name': self.long_interface_name[:31],
               'interface_name1': self.interface_name1,
               'interface_name2': self.interface_name2}
        )

    @start_task
    def req_create_interface(self,
                             if_name=FakeData.interface_name1,
                             ip=FakeData.network_allocations_ip1):
        return (
            '<NewMoverInterface name="%(if_name)s" vlanid="%(vlan)s" '
            'netMask="%(net_mask)s" device="%(device_name)s" '
            'mover="%(mover_id)s" ipAddress="%(ip)s"/>'
            % {'if_name': if_name,
               'vlan': self.vlan_id,
               'ip': ip,
               'mover_id': self.mover_id,
               'device_name': self.device_name,
               'net_mask': self.net_mask}
        )

    @start_task
    def req_create_interface_with_ipv6(self,
                                       if_name=FakeData.interface_name3,
                                       ip=FakeData.network_allocations_ip3):
        return (
            '<NewMoverInterface name="%(if_name)s" vlanid="%(vlan)s" '
            'ipVersion="IPv6" netMask="%(net_mask)s" '
            'device="%(device_name)s" '
            'mover="%(mover_id)s" ipAddress="%(ip)s"/>'
            % {'if_name': if_name,
               'vlan': self.vlan_id,
               'ip': ip,
               'mover_id': self.mover_id,
               'device_name': self.device_name,
               'net_mask': self.net_mask_v6}
        )

    @response
    def resp_create_interface_but_name_already_exist(self):
        return (
            '<Status maxSeverity="error">'
            '<Problem messageCode="13421840550" component="CS_CORE" '
            'message="%(interface_name)s : an entry with this name already '
            'exists" severity="error">'
            '<Description>Duplicate name specified</Description>'
            '<Action>Specify a unqiue name</Action>'
            '</Problem>'
            '</Status>' % {'interface_name': self.interface_name1}
        )

    @response
    def resp_create_interface_but_ip_already_exist(self):
        return (
            '<Status maxSeverity="error">'
            '<Problem messageCode="13691781136" component="CS_CORE" '
            'message="Interface %(ip)s already exists."  severity="error">'
            '<Description></Description><Action></Action>'
            '</Problem>'
            '</Status>' % {'ip': self.ip_address1}
        )

    @response
    def resp_create_interface_with_conflicted_vlan_id(self):
        return (
            '<Status maxSeverity="error">'
            '<Problem messageCode="13421850371" component="CS_CORE" '
            'message="160: Invalid VLAN change. Other interfaces on this '
            'subnet are in a different VLAN." severity="error">'
            '<Description>The operation cannot complete because other '
            'interfaces on the same subnet are in a different VLAN. '
            'The Data Mover requires all interfaces in the same subnet '
            'to be in the same VLAN.</Description>'
            '<Action>Specify a VLAN to match other interfaces in the same '
            'subnet. To move multiple interfaces to a different VLAN, '
            'first set the VLAN id on each interface to 0, '
            'and then set their VLAN id\'s to the new VLAN number.</Action>'
            '</Problem>'
            '</Status>'
        )

    @start_task
    def req_delete_interface(self, ip=FakeData.network_allocations_ip1):

        return (
            '<DeleteMoverInterface mover="%(mover_id)s" '
            'ipAddress="%(ip)s"/>' %
            {'ip': ip,
             'mover_id': self.mover_id, }
        )

    @response
    def resp_delete_interface_but_nonexistent(self):
        return (
            '<Status maxSeverity="error">'
            '<Problem messageCode="13691781134" component="APL" '
            'message="Device 192.168.237.100 does not exist." '
            'severity="error">'
            '<Description></Description>'
            '<Action></Action>'
            '</Problem>'
            '</Status>'
        )

    def cmd_get_interconnect_id(self):
        return [
            'env', 'NAS_DB=/nas', '/nas/bin/nas_cel',
            '-interconnect', '-l',
        ]

    def output_get_interconnect_id(self):
        return (
            'id name source_server destination_system destination_server\n'
            '%(id)s  loopback  %(src_server)s  nas149   %(dest_server)s\n' %
            {'id': self.interconnect_id,
             'src_server': self.mover_name,
             'dest_server': self.mover_name}
        )

    def cmd_get_physical_devices(self):
        return [
            'env', 'NAS_DB=/nas', '/nas/bin/server_sysconfig',
            self.mover_name, '-pci',
        ]

    def output_get_physical_devices(self):
        return (
            'server_2 : PCI DEVICES:\n'
            'On Board:\n'
            '  PMC QE8 Fibre Channel Controller\n'
            '    0:  fcp-0-0  IRQ: 20 addr: 5006016047a00245\n'
            '    0:  fcp-0-1  IRQ: 21 addr: 5006016147a00245\n'
            '    0:  fcp-0-2  IRQ: 22 addr: 5006016247a00245\n'
            '    0:  fcp-0-3  IRQ: 23 addr: 5006016347a00245\n'
            '  Broadcom Gigabit Ethernet Controller\n'
            '    0:  cge-1-0  IRQ: 24\n'
            '    speed=auto duplex=auto txflowctl=disable rxflowctl=disable\n'
            '    Link: Up\n'
            '    0:  cge-1-1  IRQ: 25\n'
            '    speed=auto duplex=auto txflowctl=disable rxflowctl=disable\n'
            '    Link: Down\n'
            '    0:  cge-1-2  IRQ: 26\n'
            '    speed=auto duplex=auto txflowctl=disable rxflowctl=disable\n'
            '    Link: Down\n'
            '    0:  cge-1-3  IRQ: 27\n'
            '    speed=auto duplex=auto txflowctl=disable rxflowctl=disable\n'
            '    Link: Up\n'
            'Slot: 4\n'
            '  PLX PCI-Express Switch  Controller\n'
            '    1:  PLX PEX8648  IRQ: 10\n'
        )


class DNSDomainTestData(StorageObjectTestData):
    def __init__(self):
        super(DNSDomainTestData, self).__init__()

    @start_task
    def req_create(self, ip_addr=None):
        if ip_addr is None:
            ip_addr = self.dns_ip_address

        return (
            '<NewMoverDnsDomain mover="%(mover_id)s" protocol="udp" '
            'name="%(domain_name)s" servers="%(server_ips)s"/>' %
            {'mover_id': self.mover_id,
             'domain_name': self.domain_name,
             'server_ips': ip_addr}
        )

    @start_task
    def req_delete(self):
        return (
            '<DeleteMoverDnsDomain mover="%(mover_id)s" '
            'name="%(domain_name)s"/>' %
            {'mover_id': self.mover_id,
             'domain_name': self.domain_name}
        )


class CIFSServerTestData(StorageObjectTestData):
    def __init__(self):
        super(CIFSServerTestData, self).__init__()

    @start_task
    def req_create(self, mover_id, is_vdm=True, ip_addr=None):
        if ip_addr is None:
            ip_addr = self.ip_address1

        return (
            '<NewW2KCifsServer interfaces="%(ip)s" compName="%(comp_name)s" '
            'name="%(name)s" domain="%(domain)s">'
            '<MoverOrVdm mover="%(mover_id)s" moverIdIsVdm="%(is_vdm)s"/>'
            '<Aliases><li>%(alias)s</li></Aliases>'
            '<JoinDomain userName="%(domain_user)s" '
            'password="%(domain_password)s"/>'
            '</NewW2KCifsServer>'
            % {'ip': ip_addr,
               'comp_name': self.cifs_server_name,
               'name': self.cifs_server_name[-14:],
               'mover_id': mover_id,
               'alias': self.cifs_server_name[-12:],
               'domain_user': self.domain_user,
               'domain_password': self.domain_password,
               'domain': self.domain_name,
               'is_vdm': 'true' if is_vdm else 'false'}
        )

    @query
    def req_get(self, mover_id, is_vdm=True):
        return (
            '<CifsServerQueryParams>'
            '<MoverOrVdm mover="%(mover_id)s" moverIdIsVdm="%(is_vdm)s"/>'
            '</CifsServerQueryParams>' %
            {'mover_id': mover_id,
             'is_vdm': 'true' if is_vdm else 'false'}
        )

    @response
    def resp_get_succeed(self, mover_id, is_vdm, join_domain,
                         cifs_server_name=None,
                         ip_addr=None):
        if cifs_server_name is None:
            cifs_server_name = self.cifs_server_name

        if ip_addr is None:
            ip_addr = self.ip_address1

        return (
            '<QueryStatus maxSeverity="ok"/>'
            '<CifsServer interfaces="%(ip)s" type="W2K" '
            'localUsers="false" name="%(cifsserver)s" '
            'mover="%(mover_id)s" moverIdIsVdm="%(is_vdm)s"><Aliases>'
            '<li>%(alias)s</li></Aliases><W2KServerData domain='
            '"%(domain)s" compName="%(comp_name)s" '
            'domainJoined="%(join_domain)s"/></CifsServer>'
            % {'mover_id': mover_id,
               'cifsserver': self.cifs_server_name[-14:],
               'ip': ip_addr,
               'is_vdm': 'true' if is_vdm else 'false',
               'alias': self.cifs_server_name[-12:],
               'domain': self.domain_name,
               'join_domain': 'true' if join_domain else 'false',
               'comp_name': cifs_server_name}
        )

    @response
    def resp_get_without_interface(self, mover_id, is_vdm, join_domain):
        return (
            '<QueryStatus maxSeverity="ok"/>'
            '<CifsServer interfaces="" type="W2K" localUsers="false" '
            'name="%(cifsserver)s" mover="%(mover_id)s" '
            'moverIdIsVdm="%(is_vdm)s">'
            '<Aliases><li>%(alias)s</li></Aliases>'
            '<W2KServerData domain="%(domain)s" compName="%(comp_name)s" '
            'domainJoined="%(join_domain)s"/></CifsServer>'
            % {'mover_id': mover_id,
               'cifsserver': self.cifs_server_name[-14:],
               'is_vdm': 'true' if is_vdm else 'false',
               'alias': self.cifs_server_name[-12:],
               'domain': self.domain_name,
               'join_domain': 'true' if join_domain else 'false',
               'comp_name': self.cifs_server_name}
        )

    @start_task
    def req_modify(self, mover_id, is_vdm=True, join_domain=False):
        return (
            '<ModifyW2KCifsServer mover="%(mover_id)s" '
            'moverIdIsVdm="%(is_vdm)s" name="%(cifsserver)s">'
            '<DomainSetting userName="%(username)s" password="%(pw)s" '
            'joinDomain="%(join_domain)s"/>'
            '</ModifyW2KCifsServer>'
            % {'mover_id': mover_id,
               'is_vdm': 'true' if is_vdm else 'false',
               'join_domain': 'true' if join_domain else 'false',
               'cifsserver': self.cifs_server_name[-14:],
               'username': self.domain_user,
               'pw': self.domain_password}
        )

    @response
    def resp_modify_but_already_join_domain(self):
        return (
            '<Status maxSeverity="error"> '
            '<Problem messageCode="13157007726" component="DART" '
            'message="Fake message." severity="error">'
            '<Description>Fake description</Description>'
            '<Action>Fake action.</Action>'
            '</Problem>'
            '</Status> '
        )

    @response
    def resp_modify_but_unjoin_domain(self):
        return (
            '<Status maxSeverity="error"> '
            '<Problem messageCode="13157007723" component="DART" '
            'message="Fake message." severity="error">'
            '<Description>Fake description</Description>'
            '<Action>Fake action.</Action>'
            '</Problem>'
            '</Status> '
        )

    @start_task
    def req_delete(self, mover_id, is_vdm=True):
        return (
            '<DeleteCifsServer mover="%(mover_id)s" moverIdIsVdm="%(is_vdm)s" '
            'name="%(cifsserver)s"/>'
            % {'mover_id': mover_id,
               'is_vdm': 'true' if is_vdm else 'false',
               'cifsserver': self.cifs_server_name[-14:]}
        )


class CIFSShareTestData(StorageObjectTestData):
    def __init__(self):
        super(CIFSShareTestData, self).__init__()

    @start_task
    def req_create(self, mover_id, is_vdm=True):
        return (
            '<NewCifsShare path="%(path)s" name="%(share_name)s">'
            '<MoverOrVdm mover="%(mover_id)s" moverIdIsVdm="%(is_vdm)s"/>'
            '<CifsServers><li>%(cifsserver)s</li></CifsServers>'
            '</NewCifsShare>' %
            {'path': '/' + self.share_name,
             'share_name': self.share_name,
             'mover_id': mover_id,
             'is_vdm': 'true' if is_vdm else 'false',
             'cifsserver': self.cifs_server_name[-14:]}
        )

    @start_task
    def req_delete(self, mover_id, is_vdm=True):
        return (
            '<DeleteCifsShare mover="%(mover_id)s" moverIdIsVdm="%(is_vdm)s" '
            'name="%(share_name)s">'
            '<CifsServers><li>%(cifsserver)s</li></CifsServers>'
            '</DeleteCifsShare>' %
            {'share_name': self.share_name,
             'mover_id': mover_id,
             'is_vdm': 'true' if is_vdm else 'false',
             'cifsserver': self.cifs_server_name[-12:]}
        )

    @query
    def req_get(self):
        return '<CifsShareQueryParams name="%s"/>' % self.share_name

    @response
    def resp_get_succeed(self, mover_id, is_vdm=True):
        return (
            '<QueryStatus maxSeverity="ok"/>'
            '<CifsShare path="%(path)s" fileSystem="%(fsid)s" name="%(name)s" '
            'mover="%(moverid)s" moverIdIsVdm="%(is_vdm)s">'
            '<CifsServers><li>%(alias)s</li>'
            '</CifsServers>'
            '</CifsShare>' %
            {'path': self.path,
             'fsid': self.filesystem_id,
             'name': self.share_name,
             'moverid': mover_id,
             'is_vdm': 'true' if is_vdm else 'false',
             'alias': self.cifs_server_name[-12:]}
        )

    def cmd_disable_access(self):
        cmd_str = 'sharesd %s set noaccess' % self.share_name
        return [
            'env', 'NAS_DB=/nas',
            '/nas/bin/.server_config', self.vdm_name,
            '-v', '%s' % cmd_str,
        ]

    def cmd_change_access(self, access_level=const.ACCESS_LEVEL_RW,
                          action='grant', user=None):
        if user is None:
            user = self.domain_user
        account = user + '@' + self.domain_name

        if access_level == const.ACCESS_LEVEL_RW:
            str_access = 'fullcontrol'
        else:
            str_access = 'read'

        allow_str = (
            'sharesd %(share_name)s %(action)s %(account)s=%(access)s'
            % {'share_name': self.share_name,
               'action': action,
               'account': account,
               'access': str_access}
        )
        return [
            'env', 'NAS_DB=/nas',
            '/nas/bin/.server_config', self.vdm_name,
            '-v', '%s' % allow_str,
        ]

    def cmd_get_access(self):
        get_str = 'sharesd %s dump' % self.share_name
        return [
            'env', 'NAS_DB=/nas',
            '/nas/bin/.server_config', self.vdm_name,
            '-v', '%s' % get_str,
        ]

    def output_allow_access(self):
        return (
            "Command succeeded:  :3 sharesd %(share)s grant             "
            "%(user)s@%(domain)s=fullcontrol"
            % {'share': self.share_name,
               'user': self.domain_user,
               'domain': self.domain_name}
        )

    def output_allow_access_but_duplicate_ace(self):
        return (
            '%(vdm_name)s : commands processed: 1'
            'output is complete'
            '1443422844: SMB: 6: ACE for %(domain)s\\%(user)s '
            'unchanged'
            '1443422844: ADMIN: 3: '
            'Command failed:  :23 '
            'sharesd %(share)s grant %(user)s@%(domain)s=read'
            'Error 4020: %(vdm_name)s : failed to complete command"'
            % {'share': self.share_name,
               'user': self.domain_user,
               'domain': self.domain_name,
               'vdm_name': self.vdm_name}
        )

    def output_deny_access_but_no_ace(self):
        return (
            '%(vdm_name)s : commands processed: 1'
            'output is complete'
            '1443515516: SMB: 6: No ACE found for %(domain)s\\%(user)s '
            '1443515516: ADMIN: 3: '
            'Command failed:  :26 '
            'sharesd %(share)s revoke %(user)s@%(domain)s=read'
            'Error 4020: %(vdm_name)s : failed to complete command"'
            % {'share': self.share_name,
               'user': self.domain_user,
               'domain': self.domain_name,
               'vdm_name': self.vdm_name}
        )

    def output_deny_access_but_no_user_found(self):
        return (
            '%(vdm_name)s : commands processed: 1'
            'output is complete'
            '1443520322: SMB: 6: Cannot get mapping for %(domain)s\\%(user)s '
            '1443520322: ADMIN: 3: '
            'Command failed:  :26 '
            'sharesd %(share)s revoke %(user)s@%(domain)s=read'
            'Error 4020: %(vdm_name)s : failed to complete command"'
            % {'share': self.share_name,
               'user': self.domain_user,
               'domain': self.domain_name,
               'vdm_name': self.vdm_name}
        )


class NFSShareTestData(StorageObjectTestData):
    def __init__(self):
        super(NFSShareTestData, self).__init__()

    def cmd_create(self):
        default_access = 'access=-0.0.0.0/0.0.0.0'
        return [
            'env', 'NAS_DB=/nas', '/nas/bin/server_export', self.vdm_name,
            '-option', default_access,
            self.path,
        ]

    def output_create(self):
        return "%s : done" % self.vdm_name

    def cmd_get(self):
        return [
            'env', 'NAS_DB=/nas', '/nas/bin/server_export', self.vdm_name,
            '-P', 'nfs',
            '-list', self.path,
        ]

    def output_get_succeed(self, rw_hosts, ro_hosts):
        rw_hosts = [utils.convert_ipv6_format_if_needed(ip_addr) for ip_addr in
                    rw_hosts]
        ro_hosts = [utils.convert_ipv6_format_if_needed(ip_addr) for ip_addr in
                    ro_hosts]

        if rw_hosts and ro_hosts:
            return (
                '%(mover_name)s :\nexport "%(path)s" '
                'access=%(host)s:-0.0.0.0/0.0.0.0 root=%(host)s '
                'rw=%(rw_host)s ro=%(ro_host)s\n'
                % {'mover_name': self.vdm_name,
                   'path': self.path,
                   'host': ":".join(rw_hosts + ro_hosts),
                   'rw_host': ":".join(rw_hosts),
                   'ro_host': ":".join(ro_hosts)}
            )
        elif rw_hosts:
            return (
                '%(mover_name)s :\nexport "%(path)s" '
                'access=%(host)s:-0.0.0.0/0.0.0.0 root=%(host)s '
                'rw=%(rw_host)s\n'
                % {'mover_name': self.vdm_name,
                   'host': ":".join(rw_hosts),
                   'path': self.path,
                   'rw_host': ":".join(rw_hosts)}
            )
        elif ro_hosts:
            return (
                '%(mover_name)s :\nexport "%(path)s" '
                'access=%(host)s:-0.0.0.0/0.0.0.0 root=%(host)s '
                'ro=%(ro_host)s\n'
                % {'mover_name': self.vdm_name,
                   'host': ":".join(ro_hosts),
                   'path': self.path,
                   'ro_host': ":".join(ro_hosts)}
            )
        else:
            return (
                '%(mover_name)s :\nexport "%(path)s" '
                'access=-0.0.0.0/0.0.0.0\n'
                % {'mover_name': self.vdm_name,
                   'path': self.path}
            )

    def output_get_but_not_found(self):
        return (
            '%(mover_name)s : \nError 2: %(mover_name)s : '
            'No such file or directory \n' % {'mover_name': self.vdm_name}
        )

    def cmd_delete(self):
        return [
            'env', 'NAS_DB=/nas', '/nas/bin/server_export', self.vdm_name,
            '-unexport',
            '-perm',
            self.path,
        ]

    def output_delete_succeed(self):
        return "%s : done" % self.vdm_name

    def output_delete_but_locked(self):
        return ("Error 2201: %s : unable to acquire lock(s), try later"
                % self.vdm_name)

    def cmd_set_access(self, rw_hosts, ro_hosts):
        rw_hosts = [utils.convert_ipv6_format_if_needed(ip_addr) for ip_addr in
                    rw_hosts]
        ro_hosts = [utils.convert_ipv6_format_if_needed(ip_addr) for ip_addr in
                    ro_hosts]

        access_str = ("access=%(access_hosts)s:-0.0.0.0/0.0.0.0,"
                      "root=%(root_hosts)s,rw=%(rw_hosts)s,ro=%(ro_hosts)s" %
                      {'rw_hosts': ":".join(rw_hosts),
                       'ro_hosts': ":".join(ro_hosts),
                       'root_hosts': ":".join(rw_hosts + ro_hosts),
                       'access_hosts': ":".join(rw_hosts + ro_hosts)})

        return [
            'env', 'NAS_DB=/nas', '/nas/bin/server_export', self.vdm_name,
            '-ignore',
            '-option', access_str,
            self.path,
        ]

    def output_set_access_success(self):
        return "%s : done" % self.vdm_name


class FakeEMCShareDriver(object):
    def __init__(self, enas_type='vnx'):
        self.configuration = conf.Configuration(None)
        self.configuration.append_config_values = mock.Mock(return_value=0)
        self.configuration.emc_share_backend = FakeData.emc_share_backend
        self.configuration.vnx_server_container = FakeData.mover_name
        if enas_type == 'powermax':
            self.configuration.emc_share_backend = (
                FakeData.powermax_share_backend)
            self.configuration.vmax_server_container = FakeData.mover_name
        self.configuration.emc_nas_server = FakeData.emc_nas_server
        self.configuration.emc_nas_login = FakeData.emc_nas_login
        self.configuration.emc_nas_password = FakeData.emc_nas_password
        self.configuration.share_backend_name = FakeData.share_backend_name


CIFS_SHARE = fake_share.fake_share(
    id=FakeData.share_id,
    name=FakeData.share_name,
    size=FakeData.share_size,
    share_network_id=FakeData.share_network_id,
    share_server_id=FakeData.share_server_id,
    host=FakeData.host,
    share_proto='CIFS')

NFS_SHARE = fake_share.fake_share(
    id=FakeData.share_id,
    name=FakeData.share_name,
    size=FakeData.share_size,
    share_network_id=FakeData.share_network_id,
    share_server_id=FakeData.share_server_id,
    host=FakeData.host,
    share_proto='NFS')

CIFS_RW_ACCESS = fake_share.fake_access(
    access_type='user',
    access_to=FakeData.domain_user,
    access_level='rw')

CIFS_RO_ACCESS = fake_share.fake_access(
    access_type='user',
    access_to=FakeData.domain_user,
    access_level='ro')

NFS_RW_ACCESS = fake_share.fake_access(
    access_type='ip',
    access_to=FakeData.nfs_host_ip,
    access_level='rw')

NFS_RW_ACCESS_IPV6 = fake_share.fake_access(
    access_type='ip',
    access_to=FakeData.nfs_host_ipv6,
    access_level='rw')

NFS_RO_ACCESS = fake_share.fake_access(
    access_type='ip',
    access_to=FakeData.nfs_host_ip,
    access_level='ro')

NFS_RO_ACCESS_IPV6 = fake_share.fake_access(
    access_type='ip',
    access_to=FakeData.nfs_host_ipv6,
    access_level='ro')

SHARE_SERVER = {
    'id': FakeData.share_server_id,
    'share_network': {
        'name': 'fake_share_network',
        'id': FakeData.share_network_id
    },
    'share_network_id': FakeData.share_network_id,
    'backend_details': {
        'share_server_name': FakeData.vdm_name,
        'cifs_if': FakeData.network_allocations_ip1,
        'nfs_if': FakeData.network_allocations_ip2,
    }
}

SHARE_SERVER_IPV6 = {
    'id': FakeData.share_server_id,
    'share_network': {
        'name': 'fake_share_network',
        'id': FakeData.share_network_id
    },
    'share_network_id': FakeData.share_network_id,
    'backend_details': {
        'share_server_name': FakeData.vdm_name,
        'cifs_if': FakeData.network_allocations_ip3,
        'nfs_if': FakeData.network_allocations_ip4,
    }
}

SERVER_DETAIL = {
    'share_server_name': FakeData.vdm_name,
    'cifs_if': FakeData.network_allocations_ip1,
    'nfs_if': FakeData.network_allocations_ip2,
}

SERVER_DETAIL_IPV6 = {
    'share_server_name': FakeData.vdm_name,
    'cifs_if': FakeData.network_allocations_ip3,
    'nfs_if': FakeData.network_allocations_ip4,
}

SECURITY_SERVICE = [
    {
        'type': 'active_directory',
        'domain': FakeData.domain_name,
        'dns_ip': FakeData.dns_ip_address,
        'user': FakeData.domain_user,
        'password': FakeData.domain_password
    },
]

SECURITY_SERVICE_IPV6 = [
    {
        'type': 'active_directory',
        'domain': FakeData.domain_name,
        'dns_ip': FakeData.dns_ipv6_address,
        'user': FakeData.domain_user,
        'password': FakeData.domain_password
    },
]

NETWORK_INFO = {
    'server_id': FakeData.share_server_id,
    'cidr': FakeData.cidr,
    'security_services': [
        {'type': 'active_directory',
         'domain': FakeData.domain_name,
         'dns_ip': FakeData.dns_ip_address,
         'user': FakeData.domain_user,
         'password': FakeData.domain_password},
    ],
    'segmentation_id': FakeData.segmentation_id,
    'network_type': 'vlan',
    'network_allocations': [
        {'id': FakeData.network_allocations_id1,
         'ip_address': FakeData.network_allocations_ip1,
         'ip_version': FakeData.network_allocations_ip_version1},
        {'id': FakeData.network_allocations_id2,
         'ip_address': FakeData.network_allocations_ip2,
         'ip_version': FakeData.network_allocations_ip_version2}
    ]
}

NETWORK_INFO_IPV6 = {
    'server_id': FakeData.share_server_id,
    'cidr': FakeData.cidr_v6,
    'security_services': [
        {'type': 'active_directory',
         'domain': FakeData.domain_name,
         'dns_ip': FakeData.dns_ipv6_address,
         'user': FakeData.domain_user,
         'password': FakeData.domain_password},
    ],
    'segmentation_id': FakeData.segmentation_id,
    'network_type': 'vlan',
    'network_allocations': [
        {'id': FakeData.network_allocations_id3,
         'ip_address': FakeData.network_allocations_ip3,
         'ip_version': FakeData.network_allocations_ip_version3},
        {'id': FakeData.network_allocations_id4,
         'ip_address': FakeData.network_allocations_ip4,
         'ip_version': FakeData.network_allocations_ip_version4}
    ]
}

STATS = dict(
    share_backend_name='VNX',
    vendor_name='EMC',
    storage_protocol='NFS_CIFS',
    driver_version='2.0.0,')

STATS_VMAX = dict(
    share_backend_name='VMAX',
    vendor_name='EMC',
    storage_protocol='NFS_CIFS',
    driver_version='2.0.0,')
