class EMCViPRISCSIDriver(driver.ISCSIDriver):
    """EMC ViPR iSCSI Driver"""
    
   
    def __init__(self, *args, **kwargs):
        super(EMCViPRISCSIDriver, self).__init__(*args, **kwargs)
        self.common = EMCViPRDriverCommon(
                        protocol='iSCSI',
                        default_backend_name=self.__class__.__name__,
                        configuration=self.configuration)

    def check_for_setup_error(self):
        self.common.check_for_setup_error()

    def create_volume(self, volume):
        """Creates a Volume. """
        self.common.create_volume(volume)
        self.common.setTags(volume)

    def create_cloned_volume(self, volume, src_vref):
        """Creates a cloned Volume."""
        self.common.create_cloned_volume(volume, src_vref)
        self.common.setTags(volume)                
        
    def create_volume_from_snapshot(self, volume, snapshot):
        """Creates a volume from a snapshot."""
        #self.common.create_volume_from_snapshot(volume, snapshot)
        snapshotname = snapshot['name']
        volumename = volume['name']
        exception_message = (_('Error Create Volume from Snapshot: '
                             'Volume: %(volumename)s  Snapshot: '
                             '%(snapshotname)s. Create Volume '
                             'from Snapshot is NOT supported on '
                             'EMCViPRISCSIDriver.')
                             % {'volumename': volumename,
                                'snapshotname': snapshotname})
        LOG.error(exception_message)
        raise exception.VolumeBackendAPIException(data=exception_message)

    def delete_volume(self, volume):
        """Deletes an EMC volume."""
        self.common.delete_volume(volume)

    def create_snapshot(self, snapshot):
        """Creates a snapshot."""
        self.common.create_snapshot(snapshot)

    def delete_snapshot(self, snapshot):
        """Deletes a snapshot."""
        self.common.delete_snapshot(snapshot)

    def _iscsi_location(self, ip, target, iqn, lun=None):
        return "%s:%s,%s %s %s" % (ip, self.configuration.iscsi_port, target, iqn, lun)

    def ensure_export(self, context, volume):
        """Driver entry point to get the export info for an existing volume."""
        pass

    def create_export(self, context, volume):
        """Driver entry point to get the export info for a new volume."""
        pass

    def remove_export(self, context, volume):
        """Driver exntry point to remove an export for a volume.
        """
        pass

    def check_for_export(self, context, volume_id):
        """Make sure volume is exported."""
        pass

    def initialize_connection(self, volume, connector):
        """Initializes the connection and returns connection info.

        the iscsi driver returns a driver_volume_type of 'iscsi'.
        the format of the driver data is defined as:
    
            :target_discovered:    boolean indicating whether discovery was used
    
            :target_iqn:    the IQN of the iSCSI target
    
            :target_portal:    the portal of the iSCSI target
    
            :target_lun:    the lun of the iSCSI target
    
            :volume_id:    the id of the volume (currently used by xen)
    
            :auth_method:, :auth_username:, :auth_password:
    
                the authentication details. Right now, either auth_method is not
                present meaning no authentication, or auth_method == `CHAP`
                meaning use CHAP with the specified credentials.

        Example return value::

            {
                'driver_volume_type': 'iscsi'
                'data': {
                    'target_discovered': True,
                    'target_iqn': 'iqn.2010-10.org.openstack:volume-00000001',
                    'target_portal': '127.0.0.0.1:3260',
                    'volume_id': 1,
                }
            }

        """
        initiatorNodes = []
        initiatorNode = None
        initiatorNodes.append(initiatorNode);
        initiatorPorts = []
        initiatorPort = connector['initiator']
        initiatorPorts.append(initiatorPort)
        protocol = 'iSCSI'
        hostname = connector['host']
        itls = self.common.initialize_connection(volume,
            protocol, initiatorNodes, initiatorPorts, hostname)
        
        properties = {}
        properties['target_discovered'] = False
        properties['volume_id'] = volume['id']
        if itls:
            properties['target_iqn'] = itls[0]['target']['port']
            properties['target_portal'] = itls[0]['target']['ip_address'] + ':' + itls[0]['target']['tcp_port']
            properties['target_lun'] = itls[0]['hlu']
        
        auth = volume['provider_auth']
        if auth:
            (auth_method, auth_username, auth_secret) = auth.split()
            properties['auth_method'] = auth_method
            properties['auth_username'] = auth_username
            properties['auth_password'] = auth_secret

        LOG.debug(_("ISCSI properties: %s") % (properties))
        return {
            'driver_volume_type': 'iscsi',
            'data': properties
        }

    def terminate_connection(self, volume, connector, **kwargs):
        """Disallow connection from connector"""
        initiatorNode = connector['initiator']
        initiatorPort = connector['initiator']
        protocol = 'iSCSI'
        hostname = connector['host']
        initPorts = []
        initNodes = []
        initPorts.append(initiatorPort)
        initNodes.append(initiatorNode)
        self.common.terminate_connection(volume,
            protocol, initNodes, initPorts, hostname)

    def get_volume_stats(self, refresh=False):
        """Get volume status.

        If 'refresh' is True, run update the stats first.
        """
        if refresh:
            self.update_volume_stats()

        return self._stats

    def update_volume_stats(self):
        """Retrieve stats info from virtual pool/virtual array."""
        LOG.debug(_("Updating volume stats"))
        self._stats = self.common.update_volume_stats()
class EMCViPRFCDriver(driver.FibreChannelDriver):
    """EMC ViPR FC Driver"""
    
    def __init__(self, *args, **kwargs):
        super(EMCViPRFCDriver, self).__init__(*args, **kwargs)
        self.common = EMCViPRDriverCommon(
                        protocol='FC',
                        default_backend_name=self.__class__.__name__,
                        configuration=self.configuration)

    def check_for_setup_error(self):
        self.common.check_for_setup_error()

    def create_volume(self, volume):
        """Creates a Volume. """
        self.common.create_volume(volume)
        self.common.setTags(volume)

    def create_cloned_volume(self, volume, src_vref):
        """Creates a cloned Volume."""
        self.common.create_cloned_volume(volume, src_vref)
        self.common.setTags(volume)                
        
    def create_volume_from_snapshot(self, volume, snapshot):
        """Creates a volume from a snapshot."""
        #self.common.create_volume_from_snapshot(volume, snapshot)
        snapshotname = snapshot['name']
        volumename = volume['name']
        exception_message = (_('Error Create Volume from Snapshot: '
                             'Volume: %(volumename)s  Snapshot: '
                             '%(snapshotname)s. Create Volume '
                             'from Snapshot is NOT supported on '
                             'EMCViPRFCDriver.')
                             % {'volumename': volumename,
                                'snapshotname': snapshotname})
        LOG.error(exception_message)
        raise exception.VolumeBackendAPIException(data=exception_message)

    def delete_volume(self, volume):
        """Deletes an EMC volume."""
        self.common.delete_volume(volume)

    def create_snapshot(self, snapshot):
        """Creates a snapshot."""
        self.common.create_snapshot(snapshot)

    def delete_snapshot(self, snapshot):
        """Deletes a snapshot."""
        self.common.delete_snapshot(snapshot)

    def ensure_export(self, context, volume):
        """Driver entry point to get the export info for an existing volume."""
        pass

    def create_export(self, context, volume):
        """Driver entry point to get the export info for a new volume."""
        pass

    def remove_export(self, context, volume):
        """Driver exntry point to remove an export for a volume."""
        pass

    def check_for_export(self, context, volume_id):
        """Make sure volume is exported."""
        pass

    def initialize_connection(self, volume, connector):
        """Initializes the connection and returns connection info.

        The  driver returns a driver_volume_type of 'fibre_channel'.
        The target_wwn can be a single entry or a list of wwns that
        correspond to the list of remote wwn(s) that will export the volume.
        Example return values:

            {
                'driver_volume_type': 'fibre_channel'
                'data': {
                    'target_discovered': True,
                    'target_lun': 1,
                    'target_wwn': '1234567890123',
                }
            }

            or

             {
                'driver_volume_type': 'fibre_channel'
                'data': {
                    'volume_id': 1,
                    'target_discovered': True,
                    'target_lun': 1,
                    'target_wwn': ['1234567890123', '0987654321321'],
                }
            }

        """
        properties = {}
        properties['volume_id'] = volume['id']
        properties['target_discovered'] = False
        properties['target_wwn'] = []

        protocol = 'FC'
        hostname = connector['host']
        initPorts = []
        initNodes = []
        for i in xrange(len(connector['wwpns'])):
            initiatorNode = ':'.join(re.findall('..', connector['wwnns'][i])).upper()   # Add ":" every two digits
            initiatorPort = ':'.join(re.findall('..', connector['wwpns'][i])).upper()   # Add ":" every two digits
            initPorts.append(initiatorPort)
            initNodes.append(initiatorNode)
        itls = self.common.initialize_connection(volume, protocol, initNodes, initPorts, hostname)
        if itls:
            properties['target_lun'] = itls[0]['hlu']
            for itl in itls:
                properties['target_wwn'].append(itl['target']['port'].replace(':','').lower())
        
        auth = volume['provider_auth']
        if auth:
            (auth_method, auth_username, auth_secret) = auth.split()
            properties['auth_method'] = auth_method
            properties['auth_username'] = auth_username
            properties['auth_password'] = auth_secret

        LOG.debug(_("FC properties: %s") % (properties))
        return {
            'driver_volume_type': 'fibre_channel',
            'data': properties
        }

    def terminate_connection(self, volume, connector, **kwargs):
        """Driver entry point to detach a volume from an instance."""
        protocol = 'FC'
        hostname = connector['host']
        initPorts = []
        initNodes = []
        for i in xrange(len(connector['wwpns'])):
            initiatorNode = ':'.join(re.findall('..', connector['wwnns'][i])).upper()   # Add ":" every two digits
            initiatorPort = ':'.join(re.findall('..', connector['wwpns'][i])).upper()   # Add ":" every two digits
            initPorts.append(initiatorPort)
            initNodes.append(initiatorNode)
        self.common.terminate_connection(volume, protocol, initNodes, initPorts, hostname)

    def get_volume_stats(self, refresh=False):
        """Get volume status.

        If 'refresh' is True, run update the stats first.
        """
        if refresh:
            self.update_volume_stats()

        return self._stats

    def update_volume_stats(self):
        """Retrieve stats info from virtual pool/virtual array."""
        LOG.debug(_("Updating volume stats"))
        self._stats = self.common.update_volume_stats()