def delete_port_postcommit(self, mech_context):
        """Calls cleanup process for C-Fabric.

        Case1: Baremetal deploy
                   Clear VLAN/LAG for specified physical port.
        Case2: Otherwise
                   Dissociate MAC address from the portprofile.
        """

        method = 'delete_port_postcommit'
        port = mech_context.current
        port_id = port['id']
        network_id = port['network_id']
        tenant_id = port['tenant_id']
        if fj_util.is_baremetal(port):
            if validate_baremetal_deploy(mech_context):
                params = self.get_physical_net_params(mech_context)
                try:
                    self.clear_vlan(params)
                except Exception:
                    LOG.exception(_LE("Failed to clear vlan%s."),
                        params['vlanid'])
                    raise ml2_exc.MechanismDriverError(method=method)
        elif not is_supported(mech_context.network):
            pass
        else:
            segments = mech_context.network.network_segments
            # currently supports only one segment per network
            segment = segments[0]
            vfab_id = self._get_vfab_id(segment[driver_api.PHYSICAL_NETWORK])
            vlanid = segment[driver_api.SEGMENTATION_ID]
            interface_mac = port['mac_address']

            try:
                self._driver.dissociate_mac_from_network(
                    self._switch['address'],
                    self._switch['username'],
                    self._switch['password'],
                    vfab_id,
                    vlanid,
                    interface_mac)
            except Exception:
                LOG.exception(
                    _LE("Fujitsu Mechanism: failed to dissociate MAC %s") %
                    interface_mac)
                raise ml2_exc.MechanismDriverError(method=method)
        LOG.info(
            _LI("delete port (postcommit): port_id=%(port_id)s "
                "network_id=%(network_id)s tenant_id=%(tenant_id)s"),
            {'port_id': port_id,
             'network_id': network_id, 'tenant_id': tenant_id})
    def _execute(self, cmd):
        """Execute the command on the switch."""

        self._write(cmd + "\n")
        idx, match, s = self._expect([_PROMPTS_RE])
        if idx < 0 or match is None:
            LOG.error(_LE("Unexpected response from switch: %s"), s)
            raise ml2_exc.MechanismDriverError(method="_execute")
        if s.find("<ERROR>") >= 0:
            LOG.error(_LE("Error is returned from switch: %s"), s)
            raise ml2_exc.MechanismDriverError(method="_execute")
        s = _CRLF_RE.sub(r"\n", s)
        # Remove command and prompt
        return s[s.find("\n") + 1:s.rfind("\n") + 1]
    def _associate_mac_to_port_profile(self, vfab_id, vlanid, mac_address):
        """Associates a MAC address to a port profile."""

        running_config = self.mgr.get_running_config()
        pprofile = self._create_port_profile(
            vlanid, mac_address, running_config, commit=False)
        index, profile_name = _search_vfab_pprofile(
            vfab_id, mac_address, running_config)
        if index is None:
            index = _get_available_vfab_pprofile_index(
                vfab_id, running_config)
            if index is None:
                LOG.error(_LE("No unused vfab pprofile index"))
                raise ml2_exc.MechanismDriverError(
                    method="_associate_mac_to_port_profile")
        else:
            if pprofile == profile_name:
                return
            else:
                LOG.warning(
                    _LW('Override "vfab %(vfab_id)s pprofile %(index)d vsiid '
                        'mac %(mac)s %(profile_name)s" to "vsiid mac %(mac)s '
                        '%(pprofile)s"'),
                    dict(vfab_id=vfab_id, index=index, mac=mac_address,
                         profile_name=profile_name, pprofile=pprofile))
        self.mgr.configure(
            ["vfab {vfab_id} pprofile {index} vsiid mac {mac} "
             "{pid}".format(
                 vfab_id=vfab_id, index=index, mac=mac_address, pid=pprofile)])
    def clear_vlan(self, address, username, password,
                   vfab_id, vlanid, ports, mac):
        """Clear untagged VLAN.

        @param self  CFABdriver's instance
        @param address  the string of C-Fabric IP address
        @param username  the string of C-Fabric username
        @param password  the string of C-Fabric password
        @param vfab_id  the string of VFAB ID
        @param vlanid  the string of VLAN ID
        @param ports   string of the ports which is separated by ','
        @param mac  string of the MAC address
        @return None
        """
        try:
            self.mgr.connect(address, username, password)
            config = self.mgr.get_candidate_config()
            self._dissociate_mac_from_port_profile(vfab_id, vlanid, mac,
                                                   config=config,
                                                   do_not_commit=True)
            self._clear_vlans(vfab_id, ports, config)
            self._clear_interfaces(ports, commit=True)
        except (EOFError, EnvironmentError, select.error,
                ml2_exc.MechanismDriverError):
            with excutils.save_and_reraise_exception():
                LOG.exception(_LE("CLI error"))
    def setup_vlan_with_lag(self, address, username, password,
                            vfab_id, vlanid, ports, mac):
        """Setup untagged VLAN and linkaggregation.

        @param self CFABdriver's instance
        @param address the string of C-Fabric IP address
        @param username the string of C-Fabric username
        @param password the string of C-Fabric password
        @param vfab_id the string of VFAB ID
        @param vlanid the string of VLAN ID
        @param ports  string of the ports which is separated by ','
        @param mac  string of the MAC address
        @return None
        """
        try:
            self.mgr.connect(address, username, password)
            config = self.mgr.get_candidate_config()
            modified = self._cleanup_definitions(vfab_id, vlanid, ports,
                                                 config, mac)
            self._setup_vlan_with_lag(vfab_id, vlanid, ports, config,
                                      ifg=modified, commit=True)
        except (EOFError, EnvironmentError, select.error,
                ml2_exc.MechanismDriverError):
            with excutils.save_and_reraise_exception():
                LOG.exception(_LE("CLI error"))
    def _reconnect(self):
        """Re-connect and initialize the CLI session."""

        # Close the old connection
        self._close_session()
        # Open new TELNET connection
        try:
            self._telnet = telnetlib.Telnet(
                host=self._address, port=TELNET_PORT, timeout=self._timeout)
        except EnvironmentError:
            with excutils.save_and_reraise_exception():
                LOG.exception(_LE("Connect failed to switch"))
        try:
            prompt = ""
            prompt = self._telnet.read_until(_PROMPT_LOGIN, _TIMEOUT_LOGIN)
            prompt.index(_PROMPT_LOGIN)
            self._telnet.write(self._username + "\n")
            prompt = self._telnet.read_until(_PROMPT_PASS, _TIMEOUT_LOGIN)
            prompt.index(_PROMPT_PASS)
            self._telnet.write(self._password + "\n")
            prompt = self._telnet.read_until(_PROMPT_ADMIN, _TIMEOUT_LOGIN)
            prompt.index(_PROMPT_ADMIN)
        except (EOFError, EnvironmentError, ValueError):
            if _PROMPT_BUSY in prompt:
                # Wait 3 seconds
                if self._retry_count < self._max_retry:
                    LOG.warning(_LW("Switch is busy. Wait(%ssec) and retry."),
                        _WAIT_FOR_BUSY)
                    self._retry_count += 1
                    time.sleep(_WAIT_FOR_BUSY)
                    self._reconnect()
                    return
                with excutils.save_and_reraise_exception():
                    self._retry_count = 0
                    LOG.exception(_LE("Number of retry times has reached."))
            else:
                self._telnet.close()
                self._telnet = None
                self._retry_count = 0
                with excutils.save_and_reraise_exception():
                    LOG.exception(_LE("Login failed to switch.(%s)"), prompt)

        self._retry_count = 0
        LOG.debug("Connect success to address %(address)s:%(telnet_port)s",
                  dict(address=self._address, telnet_port=TELNET_PORT))
    def _get_mode(self):
        """Gets the current mode of the switch."""

        self._read_eager()
        self._write("\n")
        idx, match, s = self._expect([_PROMPTS_RE])
        if idx < 0 or match is None:
            LOG.error(_LE("Unexpected response from switch: %s"), s)
            raise ml2_exc.MechanismDriverError(method="_get_mode")
        return _get_mode_from_match(match)
def _get_available_index(target, config):
    """Gets an available index for specified target resource."""

    indices = _INDICES[target]
    reg = _REG[target]
    available = indices - set([int(''.join(x)) for x in reg.findall(config)])
    if len(available) > 0:
        return sorted(available)[0]
    else:
        LOG.error(_LE("No unused %s index."), target)
        return None
    def _get_vfab_id(self, physical_network):
        """Get vfab_id corresponding to the physical_network."""

        try:
            vfab_id = self._physical_networks[physical_network]
        except KeyError:
            LOG.exception(
                _LE("Fujitsu Mechanism: network cannot be found in the "
                    "configured physical network"))
            raise ml2_exc.MechanismDriverError(method="_get_vfab_id")
        return vfab_id
    def clear_vlan(self, params):
        """Clear VLAN with specified port(s).

        This method will select driver's method.
        Case1: param['lag'] is True
            This method calls 'clear_vlan_with_lag' and clears VLAN and LAG.
        Case2: param['lag'] is False
            This method calls 'clear_vlan' and clears only VLAN.

        @param  params A dictionary of the return value for
                       get_physical_net_params
        @return  None
        """

        target = 'clear_vlan_with_lag'
        call_target = target if params['lag'] else 'clear_vlan'
        try:
            clear_method = getattr(self._driver, call_target)
        except AttributeError:
            LOG.exception(_LE("Unexpected error happend."))
            raise ml2_exc.MechanismDriverError(method="clear_vlan")

        try:
            # This plugin supposes 1 C-Fabric(fabric_id) management.
            # Therefore, not to identify target IP address by using
            # switch_info(mac_address).
            LOG.info(_LI("call %(target)s.  params: %(params)s"),
                {'target': call_target, 'params': params})
            clear_method(
                params['address'],
                params['username'],
                params['password'],
                params['vfab_id'],
                params['vlanid'],
                params['ports'],
                params['mac'],
                )
        except Exception:
            LOG.exception(_LE("Fujitsu Mechanism: "
                              "failed to clear vlan %s"), params['vlanid'])
            raise ml2_exc.MechanismDriverError(method="clear_vlan")
    def _parse_physical_networks(self):
        """Interpret physical_networks as physical_network:vfab_id entries."""

        for entry in cfg.CONF.fujitsu_cfab.physical_networks:
            try:
                physical_network, vfab_id = entry.split(':')
            except ValueError:
                LOG.exception(
                    _LE("Fujitsu Mechanism: illegal physical_networks entry")
                )
                raise ml2_exc.MechanismDriverError(
                    method="_parse_physical_networks")
            if not (vfab_id == VFAB_ID_DEFAULT or
                    VFAB_ID_MIN <= int(vfab_id) <= VFAB_ID_MAX):
                LOG.error(
                    _LE("Fujitsu Mechanism: illegal vfab id in "
                        "physical_networks entry")
                )
                raise ml2_exc.MechanismDriverError(
                    method="_parse_physical_networks")
            self._physical_networks[physical_network] = vfab_id
 def _read_eager(self):
     """Read readily available data."""
     if not self._telnet and self._address:
         self.connect(self._address, self._username, self._password)
     try:
         return self._telnet.read_eager()
     except (EOFError, EnvironmentError):
         self._close_session()
         try:
             self._reconnect()
             return self._telnet.read_eager()
         except (EOFError, EnvironmentError):
             with excutils.save_and_reraise_exception():
                 LOG.exception(_LE("Read failed from switch"))
    def _write(self, buffer):
        """Write a string to the switch."""

        if not self._telnet and self._address:
            self.connect(self._address, self._username, self._password)
        try:
            self._telnet.write(buffer)
        except EnvironmentError:
            self._close_session()
            try:
                self._reconnect()
                self._telnet.write(buffer)
            except EnvironmentError:
                with excutils.save_and_reraise_exception():
                    LOG.exception(_LE("Write failed to switch"))
    def _read_until(self, match):
        """Read until a given string is encountered or until timeout."""

        if not self._telnet and self._address:
            self.connect(self._address, self._username, self._password)
        try:
            return self._telnet.read_until(match, self._timeout)
        except (EOFError, EnvironmentError):
            self._close_session()
            try:
                self._reconnect()
                return self._telnet.read_until(match, self._timeout)
            except (EOFError, EnvironmentError):
                with excutils.save_and_reraise_exception():
                    LOG.exception(_LE("Read failed from switch"))
    def _expect(self, res):
        """Read until one from a list of a regular expressions matches."""

        if not self._telnet and self._address:
            self.connect(self._address, self._username, self._password)
        try:
            return self._telnet.expect(res, timeout=self._timeout)
        except (EOFError, EnvironmentError, select.error):
            self._close_session()
            try:
                self._reconnect()
                return self._telnet.expect(res, timeout=self._timeout)
            except (EOFError, EnvironmentError, select.error):
                with excutils.save_and_reraise_exception():
                    LOG.exception(_LE("Read failed from switch"))
    def create_port_postcommit(self, mech_context):
        """Calls setup process for C-Fabric.

        Case1: Baremetal deploy
                   Setup VLAN for specified physical port.
        Case2: Otherwise
                   Associate the assigned MAC address to the portprofile.
        """

        if fj_util.is_baremetal(mech_context.current):
            return

        if not is_supported(mech_context.network):
            return

        method = 'create_port_postcommit'
        port = mech_context.current
        port_id = port['id']
        network_id = port['network_id']
        tenant_id = port['tenant_id']
        segments = mech_context.network.network_segments
        # currently supports only one segment per network
        segment = segments[0]

        vfab_id = self._get_vfab_id(segment[driver_api.PHYSICAL_NETWORK])
        vlanid = segment[driver_api.SEGMENTATION_ID]

        interface_mac = port['mac_address']

        try:
            self._driver.associate_mac_to_network(self._switch['address'],
                                                  self._switch['username'],
                                                  self._switch['password'],
                                                  vfab_id,
                                                  vlanid,
                                                  interface_mac)
        except Exception:
            LOG.exception(
                _LE("Fujitsu Mechanism: failed to associate mac %s")
                % interface_mac)
            raise ml2_exc.MechanismDriverError(method=method)

        LOG.info(
            _LI("created port (postcommit): port_id=%(port_id)s "
                "network_id=%(network_id)s tenant_id=%(tenant_id)s"),
            {'port_id': port_id,
             'network_id': network_id, 'tenant_id': tenant_id})
    def _set_mode_config(self):
        """Sets the configure mode of the switch."""

        current = self._get_mode()
        if current == _MODE_CONFIG:
            return
        if current == _MODE_ADMIN:
            self._write("configure\n")
            prompt = self._read_until(_PROMPT_CONFIG)
        elif current == _MODE_CONFIG_IF:
            self._write("exit\n")
            prompt = self._read_until(_PROMPT_CONFIG)
        else:
            self._reconnect()
            self._write("configure\n")
            prompt = self._read_until(_PROMPT_CONFIG)
        if prompt.find(_PROMPT_CONFIG) < 0:
            LOG.error(_LE("Failed to set configure mode."))
            raise ml2_exc.MechanismDriverError(method="_set_mode_config")
    def dissociate_mac_from_network(self, address, username, password,
                                    vfab_id, net_id, mac):
        """Dissociates a MAC address from virtual network.

        @param self  CFABdriver's instance
        @param address  the string of C-Fabric IP address
        @param username  the string of C-Fabric username
        @param password  the string of C-Fabric password
        @param vfab_id  the string of VFAB ID
        @param net_id  the string of VLAN ID(segmentation_id for network)
        @param mac the string of MAC address
        @return None
        """

        try:
            self.mgr.connect(address, username, password)
            self._dissociate_mac_from_port_profile(vfab_id, net_id, mac)
        except (EOFError, EnvironmentError, select.error,
                ml2_exc.MechanismDriverError):
            with excutils.save_and_reraise_exception():
                LOG.exception(_LE("CLI error"))