Esempio n. 1
0
    def _get_southbound_client(self, fabric):
        """Implementation to get SouthBound Connector.

         South bound connector will be
         dynamically selected based on the configuration

        :param fabric: fabric information
        """
        fabric_info = self.fabric_configs[fabric]
        fc_ip = fabric_info.safe_get('fc_fabric_address')
        sb_connector = fabric_info.safe_get('fc_southbound_protocol')
        if sb_connector is None:
            sb_connector = self.configuration.brcd_sb_connector
        try:
            conn_factory = importutils.import_object(
                "jacket.storage.zonemanager.drivers.brocade."
                "brcd_fc_zone_connector_factory."
                "BrcdFCZoneFactory")
            client = conn_factory.get_connector(fabric_info,
                                                sb_connector.upper())
        except Exception:
            msg = _("Failed to create south bound connector for %s.") % fc_ip
            LOG.exception(msg)
            raise exception.FCZoneDriverException(msg)
        return client
    def get_active_zone_set(self):
        """Return the active zone configuration.

        Return active zoneset from fabric. When none of the configurations
        are active then it will return empty map.

        :returns: Map -- active zone set map in the following format
        {
            'zones':
                {'openstack50060b0000c26604201900051ee8e329':
                    ['50060b0000c26604', '201900051ee8e329']
                },
            'active_zone_config': 'OpenStack_Cfg'
        }
        """
        zone_set = {}
        zone = {}
        zone_member = None
        zone_name = None
        switch_data = None
        zone_set_name = None
        try:
            switch_data = self._get_switch_info(
                [zone_constant.GET_ACTIVE_ZONE_CFG])
        except exception.BrocadeZoningCliException:
            with excutils.save_and_reraise_exception():
                LOG.error(
                    _LE("Failed getting active zone set "
                        "from fabric %s"), self.switch_ip)
        try:
            for line in switch_data:
                line_split = re.split('\\t', line)
                if len(line_split) > 2:
                    line_split = [x.replace('\n', '') for x in line_split]
                    line_split = [x.replace(' ', '') for x in line_split]
                    if zone_constant.CFG_ZONESET in line_split:
                        zone_set_name = line_split[1]
                        continue
                    if line_split[1]:
                        zone_name = line_split[1]
                        zone[zone_name] = list()
                    if line_split[2]:
                        zone_member = line_split[2]
                        zone_member_list = zone.get(zone_name)
                        zone_member_list.append(zone_member)
            zone_set[zone_constant.CFG_ZONES] = zone
            zone_set[zone_constant.ACTIVE_ZONE_CONFIG] = zone_set_name
        except Exception:
            # In case of parsing error here, it should be malformed cli output.
            msg = _("Malformed zone configuration: (switch=%(switch)s "
                    "zone_config=%(zone_config)s).") % {
                        'switch': self.switch_ip,
                        'zone_config': switch_data
                    }
            LOG.exception(msg)
            raise exception.FCZoneDriverException(reason=msg)
        switch_data = None
        return zone_set
Esempio n. 3
0
 def _get_active_zone_set(self, conn):
     cfgmap = None
     try:
         cfgmap = conn.get_active_zone_set()
     except (exception.BrocadeZoningCliException,
             exception.BrocadeZoningHttpException):
         if not conn.is_supported_firmware():
             msg = _("Unsupported firmware on switch %s. Make sure "
                     "switch is running firmware v6.4 or higher"
                     ) % conn.switch_ip
             LOG.error(msg)
             raise exception.FCZoneDriverException(msg)
         with excutils.save_and_reraise_exception():
             LOG.exception(_LE("Error getting name server info."))
     except Exception as e:
         msg = (_("Failed to retrieve active zoning configuration %s")
                % six.text_type(e))
         LOG.error(msg)
         raise exception.FCZoneDriverException(msg)
     LOG.debug("Active zone set from fabric: %(cfgmap)s",
               {'cfgmap': cfgmap})
     return cfgmap
Esempio n. 4
0
 def get_zoning_status(self, fabric_ip, fabric_user, fabric_pwd,
                       fabric_port, zoning_vsan):
     """Gets zoneset status and mode."""
     statusmap = {}
     conn = None
     try:
         LOG.debug("Southbound connector: %s",
                   self.configuration.cisco_sb_connector)
         conn = importutils.import_object(
             self.configuration.cisco_sb_connector,
             ipaddress=fabric_ip,
             username=fabric_user,
             password=fabric_pwd,
             port=fabric_port,
             vsan=zoning_vsan)
         statusmap = conn.get_zoning_status()
         conn.cleanup()
     except Exception:
         msg = _("Failed to access zoneset status:%s")
         LOG.exception(msg)
         raise exception.FCZoneDriverException(msg)
     LOG.debug("Zoneset status from fabric: %s", statusmap)
     return statusmap
Esempio n. 5
0
 def get_active_zone_set(self, fabric_ip, fabric_user, fabric_pwd,
                         fabric_port, zoning_vsan):
     """Gets active zoneset config for vsan."""
     cfgmap = {}
     conn = None
     try:
         LOG.debug("Southbound connector: %s",
                   self.configuration.cisco_sb_connector)
         conn = importutils.import_object(
             self.configuration.cisco_sb_connector,
             ipaddress=fabric_ip,
             username=fabric_user,
             password=fabric_pwd,
             port=fabric_port,
             vsan=zoning_vsan)
         cfgmap = conn.get_active_zone_set()
         conn.cleanup()
     except Exception:
         msg = _("Failed to access active zoning configuration.")
         LOG.exception(msg)
         raise exception.FCZoneDriverException(msg)
     LOG.debug("Active zone set from fabric: %s", cfgmap)
     return cfgmap
    def get_zoning_status(self):
        """Return the zoning mode and session for a zoneset."""
        zone_status = {}

        try:
            switch_data = self._get_switch_info(
                [ZoneConstant.GET_ZONE_STATUS, self.fabric_vsan])
        except exception.CiscoZoningCliException:
            with excutils.save_and_reraise_exception():
                LOG.error(_LE("Failed getting zone status "
                              "from fabric %s"), self.switch_ip)
        try:
            for line in switch_data:
                # Split on non-word characters,
                line_split = re.split('[\s\[\]]+', line)
                if 'mode:' in line_split:
                    # mode: <enhanced|basic>
                    zone_status['mode'] = line_split[line_split.index('mode:')
                                                     + 1]
                    continue
                if 'session:' in line_split:
                    # session: <none|a value other than none>
                    zone_status['session'] = \
                        line_split[line_split.index('session:') + 1]
                    continue
        except Exception as ex:
            # In case of parsing error here, it should be malformed cli output.
            msg = _("Malformed zone status: (switch=%(switch)s "
                    "zone_config=%(zone_config)s)."
                    ) % {'switch': self.switch_ip,
                         'zone_status': switch_data}
            LOG.error(msg)
            exc_msg = _("Exception: %s") % six.text_type(ex)
            LOG.error(exc_msg)
            raise exception.FCZoneDriverException(reason=msg)

        return zone_status
    def get_active_zone_set(self):
        """Return the active zone configuration.

        Return active zoneset from fabric. When none of the configurations
        are active then it will return empty map.

        :returns: Map -- active zone set map in the following format
        {
            'zones':
                {'openstack50060b0000c26604201900051ee8e329':
                    ['50060b0000c26604', '201900051ee8e329']
                },
            'active_zone_config': 'OpenStack_Cfg'
        }
        """
        zone_set = {}
        zone = {}
        zone_member = None
        zone_name = None
        switch_data = None
        zone_set_name = None
        try:
            switch_data = self._get_switch_info(
                [ZoneConstant.GET_ACTIVE_ZONE_CFG, self.fabric_vsan,
                 ' | no-more'])
        except exception.CiscoZoningCliException:
            with excutils.save_and_reraise_exception():
                LOG.error(_LE("Failed getting active zone set "
                              "from fabric %s"), self.switch_ip)
        try:
            for line in switch_data:
                # Split on non-word characters,
                line_split = re.split('[\s\[\]]+', line)
                if ZoneConstant.CFG_ZONESET in line_split:
                    # zoneset name [name] vsan [vsan]
                    zone_set_name = \
                        line_split[line_split.index(ZoneConstant.CFG_ZONESET)
                                   + 2]
                    continue
                if ZoneConstant.CFG_ZONE in line_split:
                    # zone name [name] vsan [vsan]
                    zone_name = \
                        line_split[line_split.index(ZoneConstant.CFG_ZONE) + 2]
                    zone[zone_name] = list()
                    continue
                if ZoneConstant.CFG_ZONE_MEMBER in line_split:
                    # Examples:
                    # pwwn c0:50:76:05:15:9f:00:12
                    # * fcid 0x1e01c0 [pwwn 50:05:07:68:02:20:48:04] [V7K_N1P2]
                    zone_member = \
                        line_split[
                            line_split.index(ZoneConstant.CFG_ZONE_MEMBER) + 1]
                    zone_member_list = zone.get(zone_name)
                    zone_member_list.append(zone_member)

            zone_set[ZoneConstant.CFG_ZONES] = zone
            zone_set[ZoneConstant.ACTIVE_ZONE_CONFIG] = zone_set_name
        except Exception as ex:
            # In case of parsing error here, it should be malformed cli output.
            msg = _("Malformed zone configuration: (switch=%(switch)s "
                    "zone_config=%(zone_config)s)."
                    ) % {'switch': self.switch_ip,
                         'zone_config': switch_data}
            LOG.error(msg)
            exc_msg = _("Exception: %s") % six.text_type(ex)
            LOG.error(exc_msg)
            raise exception.FCZoneDriverException(reason=msg)

        return zone_set
Esempio n. 8
0
    def get_san_context(self, target_wwn_list):
        """Lookup SAN context for visible end devices.

        Look up each SAN configured and return a map of SAN (fabric IP) to
        list of target WWNs visible to the fabric.
        """
        formatted_target_list = []
        fabric_map = {}
        fabrics = [
            x.strip() for x in self.configuration.fc_fabric_names.split(',')
        ]
        LOG.debug("Fabric List: %s", fabrics)
        LOG.debug("Target wwn List: %s", target_wwn_list)
        if len(fabrics) > 0:
            for t in target_wwn_list:
                formatted_target_list.append(
                    zm_utils.get_formatted_wwn(t.lower()))
            LOG.debug("Formatted Target wwn List: %s", formatted_target_list)
            for fabric_name in fabrics:
                fabric_ip = self.fabric_configs[fabric_name].safe_get(
                    'cisco_fc_fabric_address')
                fabric_user = self.fabric_configs[fabric_name].safe_get(
                    'cisco_fc_fabric_user')
                fabric_pwd = self.fabric_configs[fabric_name].safe_get(
                    'cisco_fc_fabric_password')
                fabric_port = self.fabric_configs[fabric_name].safe_get(
                    'cisco_fc_fabric_port')
                zoning_vsan = self.fabric_configs[fabric_name].safe_get(
                    'cisco_zoning_vsan')

                # Get name server data from fabric and get the targets
                # logged in.
                nsinfo = None
                try:
                    conn = importutils.import_object(
                        self.configuration.cisco_sb_connector,
                        ipaddress=fabric_ip,
                        username=fabric_user,
                        password=fabric_pwd,
                        port=fabric_port,
                        vsan=zoning_vsan)
                    nsinfo = conn.get_nameserver_info()
                    LOG.debug("show fcns database info from fabric: %s",
                              nsinfo)
                    conn.cleanup()
                except exception.CiscoZoningCliException:
                    with excutils.save_and_reraise_exception():
                        LOG.exception(
                            _LE("Error getting show fcns database "
                                "info."))
                except Exception:
                    msg = _("Failed to get show fcns database info.")
                    LOG.exception(msg)
                    raise exception.FCZoneDriverException(msg)
                visible_targets = filter(lambda x: x in formatted_target_list,
                                         nsinfo)

                if visible_targets:
                    LOG.info(_LI("Filtered targets for SAN is: %s"),
                             {fabric_name: visible_targets})
                    # getting rid of the ':' before returning
                    for idx, elem in enumerate(visible_targets):
                        visible_targets[idx] = six.text_type(
                            visible_targets[idx]).replace(':', '')
                    fabric_map[fabric_name] = visible_targets
                else:
                    LOG.debug("No targets are in the fcns info for SAN %s",
                              fabric_name)
        LOG.debug("Return SAN context output: %s", fabric_map)
        return fabric_map
Esempio n. 9
0
    def delete_connection(self,
                          fabric,
                          initiator_target_map,
                          host_name=None,
                          storage_system=None):
        """Concrete implementation of delete_connection.

        Based on zoning policy and state of each I-T pair, list of zones
        are created for deletion. The zones are either updated deleted based
        on the policy and attach/detach state of each I-T pair.

        :param fabric: Fabric name from storage.conf file
        :param initiator_target_map: Mapping of initiator to list of targets
        """
        LOG.debug("Delete connection for fabric: %s", fabric)
        LOG.info(_LI("CiscoFCZoneDriver - Delete connection for I-T map: %s"),
                 initiator_target_map)
        fabric_ip = self.fabric_configs[fabric].safe_get(
            'cisco_fc_fabric_address')
        fabric_user = self.fabric_configs[fabric].safe_get(
            'cisco_fc_fabric_user')
        fabric_pwd = self.fabric_configs[fabric].safe_get(
            'cisco_fc_fabric_password')
        fabric_port = self.fabric_configs[fabric].safe_get(
            'cisco_fc_fabric_port')
        zoning_policy = self.configuration.zoning_policy
        zoning_policy_fab = self.fabric_configs[fabric].safe_get(
            'cisco_zoning_policy')

        if zoning_policy_fab:
            zoning_policy = zoning_policy_fab

        zoning_vsan = self.fabric_configs[fabric].safe_get('cisco_zoning_vsan')

        LOG.info(_LI("Zoning policy for fabric %s"), zoning_policy)

        statusmap_from_fabric = self.get_zoning_status(fabric_ip, fabric_user,
                                                       fabric_pwd, fabric_port,
                                                       zoning_vsan)

        if statusmap_from_fabric.get('session') == 'none':
            cfgmap_from_fabric = self.get_active_zone_set(
                fabric_ip, fabric_user, fabric_pwd, fabric_port, zoning_vsan)

            zone_names = []
            if cfgmap_from_fabric.get('zones'):
                zone_names = cfgmap_from_fabric['zones'].keys()

            # Based on zoning policy, get zone member list and push
            # changes to fabric. This operation could result in an update
            # for zone config with new member list or deleting zones from
            # active cfg.

            LOG.debug("zone config from Fabric: %s", cfgmap_from_fabric)
            for initiator_key in initiator_target_map.keys():
                initiator = initiator_key.lower()
                formatted_initiator = zm_utils.get_formatted_wwn(initiator)
                zone_map = {}
                zones_to_delete = []
                t_list = initiator_target_map[initiator_key]
                if zoning_policy == 'initiator-target':
                    # In this case, zone needs to be deleted.
                    for t in t_list:
                        target = t.lower()
                        zone_name = (driver_utils.get_friendly_zone_name(
                            zoning_policy, initiator, target, host_name,
                            storage_system,
                            self.configuration.cisco_zone_name_prefix,
                            SUPPORTED_CHARS))
                        LOG.debug("Zone name to del: %s", zone_name)
                        if (len(zone_names) > 0 and (zone_name in zone_names)):
                            # delete zone.
                            LOG.debug("Added zone to delete to list: %s",
                                      zone_name)
                            zones_to_delete.append(zone_name)

                elif zoning_policy == 'initiator':
                    zone_members = [formatted_initiator]
                    for t in t_list:
                        target = t.lower()
                        zone_members.append(zm_utils.get_formatted_wwn(target))

                    zone_name = driver_utils.get_friendly_zone_name(
                        zoning_policy, initiator, target, host_name,
                        storage_system,
                        self.configuration.cisco_zone_name_prefix,
                        SUPPORTED_CHARS)

                    if (zone_names and (zone_name in zone_names)):
                        filtered_members = filter(
                            lambda x: x not in zone_members,
                            cfgmap_from_fabric['zones'][zone_name])

                        # The assumption here is that initiator is always
                        # there in the zone as it is 'initiator' policy.
                        # We find the filtered list and if it is non-empty,
                        # add initiator to it and update zone if filtered
                        # list is empty, we remove that zone.
                        LOG.debug("Zone delete - I mode: filtered targets: %s",
                                  filtered_members)
                        if filtered_members:
                            filtered_members.append(formatted_initiator)
                            LOG.debug("Filtered zone members to update: %s",
                                      filtered_members)
                            zone_map[zone_name] = filtered_members
                            LOG.debug("Filtered zone Map to update: %s",
                                      zone_map)
                        else:
                            zones_to_delete.append(zone_name)
                else:
                    LOG.info(_LI("Zoning Policy: %s, not recognized"),
                             zoning_policy)
                LOG.debug("Final Zone map to update: %s", zone_map)
                LOG.debug("Final Zone list to delete: %s", zones_to_delete)
                conn = None
                try:
                    conn = importutils.import_object(
                        self.configuration.cisco_sb_connector,
                        ipaddress=fabric_ip,
                        username=fabric_user,
                        password=fabric_pwd,
                        port=fabric_port,
                        vsan=zoning_vsan)
                    # Update zone membership.
                    if zone_map:
                        conn.add_zones(zone_map,
                                       self.configuration.cisco_zone_activate,
                                       zoning_vsan, cfgmap_from_fabric,
                                       statusmap_from_fabric)
                    # Delete zones ~sk.
                    if zones_to_delete:
                        zone_name_string = ''
                        num_zones = len(zones_to_delete)
                        for i in range(0, num_zones):
                            if i == 0:
                                zone_name_string = (
                                    '%s%s' %
                                    (zone_name_string, zones_to_delete[i]))
                            else:
                                zone_name_string = ('%s%s%s' %
                                                    (zone_name_string, ';',
                                                     zones_to_delete[i]))

                        conn.delete_zones(
                            zone_name_string,
                            self.configuration.cisco_zone_activate,
                            zoning_vsan, cfgmap_from_fabric,
                            statusmap_from_fabric)
                    conn.cleanup()
                except Exception:
                    msg = _("Failed to update or delete zoning configuration")
                    LOG.exception(msg)
                    raise exception.FCZoneDriverException(msg)
                LOG.debug("Zones deleted successfully: %s", zone_map)
            else:
                LOG.debug("Zoning session exists VSAN: %s", zoning_vsan)
Esempio n. 10
0
    def add_connection(self,
                       fabric,
                       initiator_target_map,
                       host_name=None,
                       storage_system=None):
        """Concrete implementation of add_connection.

        Based on zoning policy and state of each I-T pair, list of zone
        members are created and pushed to the fabric to add zones. The
        new zones created or zones updated are activated based on isActivate
        flag set in storage.conf returned by volume driver after attach
        operation.

        :param fabric: Fabric name from storage.conf file
        :param initiator_target_map: Mapping of initiator to list of targets
        """

        LOG.debug("Add connection for Fabric: %s", fabric)
        LOG.info(_LI("CiscoFCZoneDriver - Add connection "
                     "for I-T map: %s"), initiator_target_map)
        fabric_ip = self.fabric_configs[fabric].safe_get(
            'cisco_fc_fabric_address')
        fabric_user = self.fabric_configs[fabric].safe_get(
            'cisco_fc_fabric_user')
        fabric_pwd = self.fabric_configs[fabric].safe_get(
            'cisco_fc_fabric_password')
        fabric_port = self.fabric_configs[fabric].safe_get(
            'cisco_fc_fabric_port')
        zoning_policy = self.configuration.zoning_policy
        zoning_policy_fab = self.fabric_configs[fabric].safe_get(
            'cisco_zoning_policy')
        if zoning_policy_fab:
            zoning_policy = zoning_policy_fab

        zoning_vsan = self.fabric_configs[fabric].safe_get('cisco_zoning_vsan')

        LOG.info(_LI("Zoning policy for Fabric %s"), zoning_policy)

        statusmap_from_fabric = self.get_zoning_status(fabric_ip, fabric_user,
                                                       fabric_pwd, fabric_port,
                                                       zoning_vsan)

        if statusmap_from_fabric.get('session') == 'none':

            cfgmap_from_fabric = self.get_active_zone_set(
                fabric_ip, fabric_user, fabric_pwd, fabric_port, zoning_vsan)
            zone_names = []
            if cfgmap_from_fabric.get('zones'):
                zone_names = cfgmap_from_fabric['zones'].keys()
                # based on zoning policy, create zone member list and
                # push changes to fabric.
                for initiator_key in initiator_target_map.keys():
                    zone_map = {}
                    initiator = initiator_key.lower()
                    t_list = initiator_target_map[initiator_key]
                    if zoning_policy == 'initiator-target':
                        for t in t_list:
                            target = t.lower()
                            zone_members = [
                                zm_utils.get_formatted_wwn(initiator),
                                zm_utils.get_formatted_wwn(target)
                            ]
                            zone_name = (driver_utils.get_friendly_zone_name(
                                zoning_policy, initiator, target, host_name,
                                storage_system,
                                self.configuration.cisco_zone_name_prefix,
                                SUPPORTED_CHARS))
                            if (len(cfgmap_from_fabric) == 0
                                    or (zone_name not in zone_names)):
                                zone_map[zone_name] = zone_members
                            else:
                                # This is I-T zoning, skip if zone exists.
                                LOG.info(
                                    _LI("Zone exists in I-T mode. "
                                        "Skipping zone creation %s"),
                                    zone_name)
                    elif zoning_policy == 'initiator':
                        zone_members = [zm_utils.get_formatted_wwn(initiator)]
                        for t in t_list:
                            target = t.lower()
                            zone_members.append(
                                zm_utils.get_formatted_wwn(target))

                        zone_name = (driver_utils.get_friendly_zone_name(
                            zoning_policy, initiator, target, host_name,
                            storage_system,
                            self.configuration.cisco_zone_name_prefix,
                            SUPPORTED_CHARS))

                        if len(zone_names) > 0 and (zone_name in zone_names):
                            zone_members = zone_members + filter(
                                lambda x: x not in zone_members,
                                cfgmap_from_fabric['zones'][zone_name])
                        zone_map[zone_name] = zone_members
                    else:
                        msg = _("Zoning Policy: %s, not"
                                " recognized") % zoning_policy
                        LOG.error(msg)
                        raise exception.FCZoneDriverException(msg)

                LOG.info(_LI("Zone map to add: %s"), zone_map)

                if len(zone_map) > 0:
                    conn = None
                    try:
                        conn = importutils.import_object(
                            self.configuration.cisco_sb_connector,
                            ipaddress=fabric_ip,
                            username=fabric_user,
                            password=fabric_pwd,
                            port=fabric_port,
                            vsan=zoning_vsan)
                        conn.add_zones(zone_map,
                                       self.configuration.cisco_zone_activate,
                                       zoning_vsan, cfgmap_from_fabric,
                                       statusmap_from_fabric)
                        conn.cleanup()
                    except exception.CiscoZoningCliException as cisco_ex:
                        msg = _("Exception: %s") % six.text_type(cisco_ex)
                        raise exception.FCZoneDriverException(msg)
                    except Exception:
                        msg = _("Failed to add zoning configuration.")
                        LOG.exception(msg)
                        raise exception.FCZoneDriverException(msg)
                LOG.debug("Zones added successfully: %s", zone_map)
            else:
                LOG.debug("Zoning session exists VSAN: %s", zoning_vsan)
Esempio n. 11
0
    def get_san_context(self, target_wwn_list):
        """Lookup SAN context for visible end devices.

        Look up each SAN configured and return a map of SAN (fabric IP) to
        list of target WWNs visible to the fabric.
        """
        formatted_target_list = []
        fabric_map = {}
        fc_fabric_names = self.configuration.fc_fabric_names
        fabrics = [x.strip() for x in fc_fabric_names.split(',')]
        LOG.debug("Fabric List: %(fabrics)s", {'fabrics': fabrics})
        LOG.debug("Target WWN list: %(targetwwns)s",
                  {'targetwwns': target_wwn_list})
        if len(fabrics) > 0:
            for t in target_wwn_list:
                formatted_target_list.append(utils.get_formatted_wwn(t))
            LOG.debug("Formatted target WWN list: %(targetlist)s",
                      {'targetlist': formatted_target_list})
            for fabric_name in fabrics:
                conn = self._get_southbound_client(fabric_name)

                # Get name server data from fabric and get the targets
                # logged in.
                nsinfo = None
                try:
                    nsinfo = conn.get_nameserver_info()
                    LOG.debug("Name server info from fabric: %(nsinfo)s",
                              {'nsinfo': nsinfo})
                except (exception.BrocadeZoningCliException,
                        exception.BrocadeZoningHttpException):
                    if not conn.is_supported_firmware():
                        msg = _("Unsupported firmware on switch %s. Make sure "
                                "switch is running firmware v6.4 or higher"
                                ) % conn.switch_ip
                        LOG.exception(msg)
                        raise exception.FCZoneDriverException(msg)
                    with excutils.save_and_reraise_exception():
                        LOG.exception(_LE("Error getting name server info."))
                except Exception:
                    msg = _("Failed to get name server info.")
                    LOG.exception(msg)
                    raise exception.FCZoneDriverException(msg)
                finally:
                    conn.cleanup()
                visible_targets = filter(
                    lambda x: x in formatted_target_list,
                    nsinfo)

                if visible_targets:
                    LOG.info(_LI("Filtered targets for SAN is: %(targets)s"),
                             {'targets': visible_targets})
                    # getting rid of the ':' before returning
                    for idx, elem in enumerate(visible_targets):
                        visible_targets[idx] = str(
                            visible_targets[idx]).replace(':', '')
                    fabric_map[fabric_name] = visible_targets
                else:
                    LOG.debug("No targets found in the nameserver "
                              "for fabric: %(fabric)s",
                              {'fabric': fabric_name})
        LOG.debug("Return SAN context output: %(fabricmap)s",
                  {'fabricmap': fabric_map})
        return fabric_map
Esempio n. 12
0
    def delete_connection(self, fabric, initiator_target_map, host_name=None,
                          storage_system=None):
        """Concrete implementation of delete_connection.

        Based on zoning policy and state of each I-T pair, list of zones
        are created for deletion. The zones are either updated deleted based
        on the policy and attach/detach state of each I-T pair.

        :param fabric: Fabric name from storage.conf file
        :param initiator_target_map: Mapping of initiator to list of targets
        """
        LOG.info(_LI("BrcdFCZoneDriver - Delete connection for fabric "
                 "%(fabric)s for I-T map: %(i_t_map)s"),
                 {'fabric': fabric,
                  'i_t_map': initiator_target_map})
        zoning_policy = self.configuration.zoning_policy
        zoning_policy_fab = self.fabric_configs[fabric].safe_get(
            'zoning_policy')
        zone_name_prefix = self.fabric_configs[fabric].safe_get(
            'zone_name_prefix')
        zone_activate = self.fabric_configs[fabric].safe_get(
            'zone_activate')
        if zoning_policy_fab:
            zoning_policy = zoning_policy_fab
        LOG.info(_LI("Zoning policy for fabric %(policy)s"),
                 {'policy': zoning_policy})
        conn = self._get_southbound_client(fabric)
        cfgmap_from_fabric = self._get_active_zone_set(conn)

        zone_names = []
        if cfgmap_from_fabric.get('zones'):
            zone_names = cfgmap_from_fabric['zones'].keys()

        # Based on zoning policy, get zone member list and push changes to
        # fabric. This operation could result in an update for zone config
        # with new member list or deleting zones from active cfg.
        LOG.debug("zone config from Fabric: %(cfgmap)s",
                  {'cfgmap': cfgmap_from_fabric})
        for initiator_key in initiator_target_map.keys():
            initiator = initiator_key.lower()
            formatted_initiator = utils.get_formatted_wwn(initiator)
            zone_map = {}
            zones_to_delete = []
            t_list = initiator_target_map[initiator_key]
            if zoning_policy == 'initiator-target':
                # In this case, zone needs to be deleted.
                for t in t_list:
                    target = t.lower()
                    zone_name = driver_utils.get_friendly_zone_name(
                        zoning_policy,
                        initiator,
                        target,
                        host_name,
                        storage_system,
                        zone_name_prefix,
                        SUPPORTED_CHARS)
                    LOG.debug("Zone name to delete: %(zonename)s",
                              {'zonename': zone_name})
                    if len(zone_names) > 0 and (zone_name in zone_names):
                        # delete zone.
                        LOG.debug("Added zone to delete to list: %(zonename)s",
                                  {'zonename': zone_name})
                        zones_to_delete.append(zone_name)

            elif zoning_policy == 'initiator':
                zone_members = [formatted_initiator]
                for t in t_list:
                    target = t.lower()
                    zone_members.append(utils.get_formatted_wwn(target))

                zone_name = driver_utils.get_friendly_zone_name(
                    zoning_policy,
                    initiator,
                    target,
                    host_name,
                    storage_system,
                    zone_name_prefix,
                    SUPPORTED_CHARS)

                if (zone_names and (zone_name in zone_names)):
                    filtered_members = filter(
                        lambda x: x not in zone_members,
                        cfgmap_from_fabric['zones'][zone_name])

                    # The assumption here is that initiator is always there
                    # in the zone as it is 'initiator' policy. We find the
                    # filtered list and if it is non-empty, add initiator
                    # to it and update zone if filtered list is empty, we
                    # remove that zone.
                    LOG.debug("Zone delete - initiator mode: "
                              "filtered targets: %(targets)s",
                              {'targets': filtered_members})
                    if filtered_members:
                        filtered_members.append(formatted_initiator)
                        LOG.debug("Filtered zone members to update: "
                                  "%(members)s", {'members': filtered_members})
                        zone_map[zone_name] = filtered_members
                        LOG.debug("Filtered zone map to update: %(zonemap)s",
                                  {'zonemap': zone_map})
                    else:
                        zones_to_delete.append(zone_name)
            else:
                LOG.warning(_LW("Zoning policy not recognized: %(policy)s"),
                            {'policy': zoning_policy})
            LOG.debug("Final zone map to update: %(zonemap)s",
                      {'zonemap': zone_map})
            LOG.debug("Final zone list to delete: %(zones)s",
                      {'zones': zones_to_delete})
            try:
                # Update zone membership.
                if zone_map:
                    conn.add_zones(
                        zone_map, zone_activate,
                        cfgmap_from_fabric)
                # Delete zones ~sk.
                if zones_to_delete:
                    zone_name_string = ''
                    num_zones = len(zones_to_delete)
                    for i in range(0, num_zones):
                        if i == 0:
                            zone_name_string = (
                                '%s%s' % (
                                    zone_name_string, zones_to_delete[i]))
                        else:
                            zone_name_string = '%s;%s' % (
                                zone_name_string, zones_to_delete[i])

                    conn.delete_zones(
                        zone_name_string, zone_activate,
                        cfgmap_from_fabric)
            except (exception.BrocadeZoningCliException,
                    exception.BrocadeZoningHttpException) as brocade_ex:
                raise exception.FCZoneDriverException(brocade_ex)
            except Exception:
                msg = _("Failed to update or delete zoning "
                        "configuration.")
                LOG.exception(msg)
                raise exception.FCZoneDriverException(msg)
            finally:
                conn.cleanup()
Esempio n. 13
0
    def add_connection(self, fabric, initiator_target_map, host_name=None,
                       storage_system=None):
        """Concrete implementation of add_connection.

        Based on zoning policy and state of each I-T pair, list of zone
        members are created and pushed to the fabric to add zones. The
        new zones created or zones updated are activated based on isActivate
        flag set in storage.conf returned by volume driver after attach
        operation.

        :param fabric: Fabric name from storage.conf file
        :param initiator_target_map: Mapping of initiator to list of targets
        """
        LOG.info(_LI("BrcdFCZoneDriver - Add connection for fabric "
                     "%(fabric)s for I-T map: %(i_t_map)s"),
                 {'fabric': fabric,
                  'i_t_map': initiator_target_map})
        zoning_policy = self.configuration.zoning_policy
        zoning_policy_fab = self.fabric_configs[fabric].safe_get(
            'zoning_policy')
        zone_name_prefix = self.fabric_configs[fabric].safe_get(
            'zone_name_prefix')
        zone_activate = self.fabric_configs[fabric].safe_get(
            'zone_activate')
        if zoning_policy_fab:
            zoning_policy = zoning_policy_fab
        LOG.info(_LI("Zoning policy for Fabric %(policy)s"),
                 {'policy': zoning_policy})
        if (zoning_policy != 'initiator'
                and zoning_policy != 'initiator-target'):
            LOG.info(_LI("Zoning policy is not valid, "
                         "no zoning will be performed."))
            return

        client = self._get_southbound_client(fabric)
        cfgmap_from_fabric = self._get_active_zone_set(client)

        zone_names = []
        if cfgmap_from_fabric.get('zones'):
            zone_names = cfgmap_from_fabric['zones'].keys()
        # based on zoning policy, create zone member list and
        # push changes to fabric.
        for initiator_key in initiator_target_map.keys():
            zone_map = {}
            initiator = initiator_key.lower()
            target_list = initiator_target_map[initiator_key]
            if zoning_policy == 'initiator-target':
                for target in target_list:
                    zone_members = [utils.get_formatted_wwn(initiator),
                                    utils.get_formatted_wwn(target)]
                    zone_name = driver_utils.get_friendly_zone_name(
                        zoning_policy,
                        initiator,
                        target,
                        host_name,
                        storage_system,
                        zone_name_prefix,
                        SUPPORTED_CHARS)
                    if (len(cfgmap_from_fabric) == 0 or (
                            zone_name not in zone_names)):
                        zone_map[zone_name] = zone_members
                    else:
                        # This is I-T zoning, skip if zone already exists.
                        LOG.info(_LI("Zone exists in I-T mode. Skipping "
                                     "zone creation for %(zonename)s"),
                                 {'zonename': zone_name})
            elif zoning_policy == 'initiator':
                zone_members = [utils.get_formatted_wwn(initiator)]
                for target in target_list:
                    zone_members.append(utils.get_formatted_wwn(target))

                zone_name = driver_utils.get_friendly_zone_name(
                    zoning_policy,
                    initiator,
                    target,
                    host_name,
                    storage_system,
                    zone_name_prefix,
                    SUPPORTED_CHARS)

                if len(zone_names) > 0 and (zone_name in zone_names):
                    zone_members = zone_members + filter(
                        lambda x: x not in zone_members,
                        cfgmap_from_fabric['zones'][zone_name])

                zone_map[zone_name] = zone_members

            LOG.info(_LI("Zone map to add: %(zonemap)s"),
                     {'zonemap': zone_map})

            if len(zone_map) > 0:
                try:
                    client.add_zones(
                        zone_map, zone_activate,
                        cfgmap_from_fabric)
                except (exception.BrocadeZoningCliException,
                        exception.BrocadeZoningHttpException) as brocade_ex:
                    raise exception.FCZoneDriverException(brocade_ex)
                except Exception:
                    msg = _("Failed to add zoning configuration.")
                    LOG.exception(msg)
                    raise exception.FCZoneDriverException(msg)
                LOG.debug("Zones added successfully: %(zonemap)s",
                          {'zonemap': zone_map})
            client.cleanup()