def unassign_floating_ip(self, floating_ip, fixed_ip):
        """Deletes SNAT and DNAT rules for given floating ip and fixed ip."""

        if self._external_gw_info is None:
            raise v_exc.VRouterOperationError(
                ip_address=self.address,
                reason='External gateway not configured')

        cmd_list = []

        # Check the cache for nat rules
        dict_key = self._get_floating_ip_key(floating_ip, fixed_ip)
        if dict_key in self._floating_ip_dict:

            # Get the NAT rules from the cache and delete them
            nat_rule = self._floating_ip_dict[dict_key]
            self._delete_snat_rule_cmd(cmd_list, nat_rule)
            self._delete_dnat_rule_cmd(cmd_list, nat_rule)

            # Delete the floating ip in external gateway interface
            gw_net = netaddr.IPNetwork(self._external_gw_info.get_ip_address())
            self._delete_ethernet_ip_cmd(
                cmd_list, self._external_gw_info.get_ethernet_if_id(),
                '{0}/{1}'.format(floating_ip, gw_net.prefixlen))
        else:
            raise v_exc.VRouterOperationError(
                ip_address=self.address,
                reason='NAT rule not found for floating ip {0}'.format(
                    floating_ip))

        self.exec_cmd_batch(cmd_list)

        if dict_key in self._floating_ip_dict:
            self._floating_ip_dict.pop(dict_key)
    def _show_cmd(self, user_cmd):
        # TODO(asaprykin): Need to verify error handling

        op_cmd = '/rest/op/show/{0}'.format(user_cmd)
        response = self._rest_call("POST", op_cmd)
        self._check_response(response)

        op_url = response.headers['Location']
        if op_url is None:
            raise v_exc.VRouterOperationError(ip_address=self.address,
                                              reason='REST API Op URL is None')

        op_url = "/" + op_url

        output = []

        while True:
            response = self._rest_call('GET', op_url)
            if response.status_code == requests.codes.GONE:
                break

            if response.text:
                output.append(response.text)

        self._rest_call("DELETE", op_url)
        return ''.join(output)
    def exec_cmd_batch(self, user_cmd_list):
        """Executes the given configuration command list.

        Commits and Saves the configuration changes to the startup config.
        """
        response = self._rest_call("POST", "/rest/conf")
        self._check_response(response)

        config_url = response.headers['Location']
        if config_url is None:
            raise v_exc.VRouterOperationError(
                ip_address=self.address,
                reason='REST API configuration URL is null')

        config_url = "/" + config_url
        for user_cmd in user_cmd_list:
            url = user_cmd.make_url(config_url)
            LOG.debug("Vyatta vRouter REST API: Config command %s", url)
            response = self._rest_call("PUT", url)
            self._check_response(response, config_url)

        response = self._rest_call("POST", config_url + "/commit")
        LOG.debug("Vyatta vRouter REST API: %s/commit", config_url)
        self._check_response(response, config_url)

        response = self._rest_call("POST", config_url + "/save")
        LOG.debug("Vyatta vRouter REST API: %s/save", config_url)
        self._check_response(response, config_url)

        response = self._rest_call("DELETE", config_url)
        self._check_response(response)
    def assign_floating_ip(self, floating_ip, fixed_ip):
        """Creates SNAT and DNAT rules for given floating ip and fixed ip."""

        if self._external_gw_info is None:
            raise v_exc.VRouterOperationError(
                ip_address=self.address,
                reason='External gateway not configured')

        cmd_list = []

        ext_if_id = self._external_gw_info.get_ethernet_if_id()

        # Get the next NAT rule number and add the NAT rule
        nat_rule_num = self._get_next_nat_floating_ip_rule_num()
        self._add_snat_rule_cmd(cmd_list, nat_rule_num, ext_if_id, fixed_ip,
                                floating_ip)
        self._add_dnat_rule_cmd(cmd_list, nat_rule_num, ext_if_id, floating_ip,
                                fixed_ip)

        # Set the floating ip in external gateway interface
        gw_net = netaddr.IPNetwork(self._external_gw_info.get_ip_address())
        self._set_ethernet_ip(cmd_list,
                              self._external_gw_info.get_ethernet_if_id(),
                              '{0}/{1}'.format(floating_ip, gw_net.prefixlen))

        self.exec_cmd_batch(cmd_list)

        # Store SNAT and DNAT rule in cache
        dict_key = self._get_floating_ip_key(floating_ip, fixed_ip)
        self._floating_ip_dict[dict_key] = nat_rule_num
    def _get_next_nat_subnet_ip_rule_num(self):
        """Returns the next NAT rule number for subnet ip."""

        if self._nat_subnet_ip_rule_num >= self._MAX_NAT_SUBNET_IP_RULE_NUM:
            raise v_exc.VRouterOperationError(
                ip_address=self.address,
                reason='Max NAT Subnet IP rule count reached')

        self._nat_subnet_ip_rule_num += 1
        return self._nat_subnet_ip_rule_num
    def _get_next_nat_exclude_rule_num(self):
        """Returns the next NAT exclude rule number for VPN purposes"""

        if self._nat_exclude_rule_num >= self._MAX_NAT_EXCLUDE_RULE_NUM:
            raise v_exc.VRouterOperationError(
                ip_address=self.address,
                reason='Max NAT Exclude rule count reached')

        self._nat_exclude_rule_num += 1
        return self._nat_exclude_rule_num
    def _get_next_nat_floating_ip_rule_num(self):
        """Returns the next NAT rule number for floating ip."""

        if (self._nat_floating_ip_rule_num >=
                self._MAX_NAT_FLOATING_IP_RULE_NUM):
            raise v_exc.VRouterOperationError(
                ip_address=self.address,
                reason='Max NAT Floating IP rule count reached')

        self._nat_floating_ip_rule_num += 1
        return self._nat_floating_ip_rule_num
    def _find_interface(self, mac_address):
        mac_address = mac_address.strip().lower()
        ifaces = self._get_interfaces()
        for iface in ifaces:
            if iface['mac_address'] == mac_address:
                return iface

        raise v_exc.VRouterOperationError(
            ip_address=self.address,
            reason='Ethernet interface with Mac-address {0} does not exist'.
            format(mac_address))
    def _clear_gw_configuration(self, cmd_list):
        # If external gateway info was cached before
        # then clear the gateway router info
        if self._external_gw_info is not None:
            self._delete_external_gateway_if_cmd(cmd_list,
                                                 self._external_gw_info)
        else:
            raise v_exc.VRouterOperationError(
                ip_address=self.address,
                reason='External gateway not already configured')

        # Execute the configuration commands
        self.exec_cmd_batch(cmd_list)
    def _get_config_cmd(self, user_cmd):
        """Executes the given "get config" command."""

        response = self._rest_call("POST", "/rest/conf")
        self._check_response(response)

        config_url = response.headers['Location']
        if config_url is None:
            raise v_exc.VRouterOperationError(
                ip_address=self.address,
                reason='REST API Configuration URL is None')
        config_url = "/" + config_url
        config_cmd = '{0}/{1}/'.format(config_url, user_cmd)
        response = self._rest_call("GET", config_cmd)
        self._check_response(response)
        data = jsonutils.loads(response.text)
        self._rest_call("DELETE", config_url)
        return data
    def _check_response(self, response, config_url=None, session=None):

        if session is None:
            session = requests

        if response.status_code not in (requests.codes.OK,
                                        requests.codes.CREATED):
            LOG.error(
                _LE('Vyatta vRouter REST API: Response Status : '
                    '%(status)s Reason: %(reason)s') % {
                        'status': response.status_code,
                        'reason': response.reason
                    })

            if config_url is not None:
                self._rest_call("DELETE", config_url, session=session)

            raise v_exc.VRouterOperationError(ip_address=self.address,
                                              reason=response.reason)
    def _process_model(self):

        model = None
        show_output = self._show_cmd("version")
        LOG.debug('Vyatta vRouter REST API: Version output : %s', show_output)
        if show_output is not None:
            ma = re.compile(".+Description.+Brocade Vyatta\D+(\d+).+",
                            re.DOTALL)
            result = ma.match(show_output)
            LOG.debug('Vyatta vRouter REST API: Result : %s', result)
            if result is not None:
                model_str = result.group(1)
                LOG.debug('Vyatta vRouter REST API: Result : %s', model_str)
                model = int(model_str) / 100
                LOG.debug('Vyatta vRouter REST API: Result : %s', model)
                if model in (self._VROUTER_VSE_MODEL, self._VROUTER_VR_MODEL):
                    self._vrouter_model = model

        LOG.debug('Vyatta vRouter REST API: Version : %s', self._vrouter_model)
        if self._vrouter_model is None:
            raise v_exc.VRouterOperationError(
                ip_address=self.address,
                reason='Unable to process vRouter model info: {0}'.format(
                    model))