neutron删除vpn时,iptables规则没有删除的bug修复

来源:互联网 发布:灵云网络机顶合s3刷机 编辑:程序博客网 时间:2024/05/16 05:07
    本人新开博客,主要从事openstack的二次开发,熟悉各个模块。博客主要会写一些平时遇到的问题及解决办法,希望能够帮到初涉云计算尤其是openstack的朋友,如果需要转载请注明出处:http://blog.csdn.net/ivy_feifei,有什么问题欢迎留言讨论,如博文有误,欢迎指出,谢谢!

bug描述:当删除vpn时,对应的iptables规则没有删除:

1
2
3
Chain neutron-vpn-agen-POSTROUTING (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    2   168 ACCEPT     all  --  *      *       10.10.10.0/24        9.9.9.0/24          policy match dir out pol ipsec 

查看日志:
1
2
2014-12-01 15:36:30.732 36570 WARNING neutron.agent.linux.iptables_manager [req-3ff1e7a5-e7b5-4338-85f9-2d5466b6ccba None] 
Tried to remove rule that was not there: 'POSTROUTING' u'-s 10.10.10.0/24 -d 9.9.9.0/24 -m policy --dir out --pol ipsec -j ACCEPT ' True False

貌似规则没有正确匹配。
查看代码:
1 这里主要是删除router里的iptables规则
1
2
3
4
5
6
7
8
9
10
11
12
13
    def destroy_router(self, process_id):
        """Handling destroy_router event.
 
        Agent calls this method, when the process namespace
        is deleted.
        """
        if process_id in self.processes:
            process = self.processes[process_id]
            process.disable()
            vpnservice = process.vpnservice
            if vpnservice:
                self._update_nat(vpnservice, self.agent.remove_nat_rule)
            del self.processes[process_id]

2 更新iptables nat表,apply函数主要是锁定iptables,并且使改动生效。如果func函数抛出异常,则不会执行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def _update_nat(self, vpnservice, func):
        """Setting up nat rule in iptables.
 
        We need to setup nat rule for ipsec packet.
        :param vpnservice: vpnservices
        :param func: self.add_nat_rule or self.remove_nat_rule
        """
        local_cidr = vpnservice['subnet']['cidr']
        router_id = vpnservice['router_id']
        for ipsec_site_connection in vpnservice['ipsec_site_connections']:
            for peer_cidr in ipsec_site_connection['peer_cidrs']:
                func(
                    router_id,
                    'POSTROUTING',
                    '-s %s -d %s -m policy '
                    '--dir out --pol ipsec '
                    '-j ACCEPT ' % (local_cidr, peer_cidr),
                    top=True)
        self.agent.iptables_apply(router_id)

3 上面的func就是self.agent.remove_nat_rule,这里使用iptables管理模块删除规则
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    def remove_nat_rule(self, router_id, chain, rule, top=False):
        """Remove nat rule in namespace.
 
        :param router_id: router_id
        :param chain: a string of chain name
        :param rule: a string of rule
        :param top: unused
            needed to have same argument with add_nat_rule
        """
        router_info = self.router_info.get(router_id)
        if not router_info:
            return
        router_info.iptables_manager.ipv4['nat'].remove_rule(
            chain, rule)

4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    def remove_rule(self, chain, rule, wrap=True, top=False):
        """Remove a rule from a chain.
 
        Note: The rule must be exactly identical to the one that was added.
        You cannot switch arguments around like you can with the iptables
        CLI tool.
 
        """
        chain = get_chain_name(chain, wrap)
        try:
            if '$' in rule:
                rule = ' '.join(
                    self._wrap_target_chain(e, wrap) for in rule.split(' '))
 
            self.rules.remove(IptablesRule(chain, rule, wrap, top,
                                           self.wrap_name))
            if not wrap:
                self.remove_rules.append(IptablesRule(chain, rule, wrap, top,
                                                      self.wrap_name))
        except ValueError:
            LOG.warn(_('Tried to remove rule that was not there:'
                       ' %(chain)r %(rule)r %(wrap)r %(top)r'),
                     {'chain': chain, 'rule': rule,
                      'top': top, 'wrap': wrap})
5 这里主要是在POSTROUTING链里轮询做匹配,如果规则的参数完全匹配上,就返回True,否则是False,如果是False就抛出上面的异常,且删除规则失败。上面提到的apply函数不会执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class IptablesRule(object):
    """An iptables rule.
 
    You shouldn't need to use this class directly, it's only used by
    IptablesManager.
 
    """
 
    def __init__(self, chain, rule, wrap=True, top=False,
                 binary_name=binary_name, tag=None):
        self.chain = get_chain_name(chain, wrap)
        self.rule = rule
        self.wrap = wrap
        self.top = top
        self.wrap_name = binary_name[:16]
        self.tag = tag
 
    def __eq__(self, other):
        return ((self.chain == other.chain) and
                (self.rule == other.rule) and
                (self.top == other.top) and
                (self.wrap == other.wrap))

比对结果:

6. 这里在作比对时top不同,所以没有匹配上,经过查找代码发现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    def add_nat_rule(self, router_id, chain, rule, top=False):
        """Add nat rule in namespace.
 
        :param router_id: router_id
        :param chain: a string of chain name
        :param rule: a string of rule
        :param top: if top is true, the rule
            will be placed on the top of chain
            Note if there is no rotuer, this method do nothing
        """
        router_info = self.router_info.get(router_id)
        if not router_info:
            return
        router_info.iptables_manager.ipv4['nat'].add_rule(
            chain, rule, top=top)

在添加时top是传入True的,而前面第2步时,也传入了True,但是在往下传时就没有传top了,所使用了默认值false,所以这里只要继续传入top就可以了。
改动如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    def remove_nat_rule(self, router_id, chain, rule, top=False):
        """Remove nat rule in namespace.
 
        :param router_id: router_id
        :param chain: a string of chain name
        :param rule: a string of rule
        :param top: unused
            needed to have same argument with add_nat_rule
        """
        router_info = self.router_info.get(router_id)
        if not router_info:
            return
        router_info.iptables_manager.ipv4['nat'].remove_rule(
            chain, rule,top=top)

问题解决
0 0
原创粉丝点击