neutron/db/l3_dvr_db.py
为 l3 router 增加 dvr 的处理
router_device_owners = (
l3_db.L3_NAT_db_mixin.router_device_owners +
(const.DEVICE_OWNER_DVR_INTERFACE,
const.DEVICE_OWNER_ROUTER_SNAT,
const.DEVICE_OWNER_AGENT_GW))
extra_attributes = (
l3_attrs_db.ExtraAttributesMixin.extra_attributes + [{
'name': "distributed",
'default': cfg.CONF.router_distributed
}])
- 调用
L3_NAT_dbonly_mixin._get_router_info_list
获取与 router_ids 所代表的 router 有关的详细数据(包含 port 和 floating ip) - 获取 distributed router 的 id,获取与 distributed router 绑定的 floating ip
- 若是含有 与 distributed router 绑定的 floating ip,则:
- 调用
core_plugin.get_ports
获取与这些 floating ip 绑定的 port - 获取那些与该 host 绑定的 port,或者将要迁移到该 host 上的 port
- 若是上一步获取的 port绑定了 floating ip
- 调用
_get_dvr_service_port_hostid
获取提供 dvr 服务的 port 的 host_id 属性 - 调用
_get_dvr_migrating_service_port_hostid
获取提供 dvr 服务的 port 准备迁移到的 host 的 id - 调用
_process_routers
为 router 数据填充_snat_router_interfaces
属性 - 调用
_process_floating_ips_dvr
为 router 数据填充_floatingips
和_floatingip_agent_interfaces
属性 - 调用
L3_NAT_dbonly_mixin._populate_mtu_and_subnets_for_ports
完善 port 的 subnet 数据和 mtu - 调用
ExtraRoute_dbonly_mixin._process_interfaces
为 router 增加_interfaces
属性 - 返回 router 的所有数据
我觉得这个过程肯定是慢慢丰富起来的,根据 l3 agent 的需求
- 查询数据库
RouterL3AgentBinding
获取所有与 routers 有关的绑定记录 - 完善各个 router 的数据(添加
gw_port_id
、gw_port
、enable_snat
、gw_port_host
属性)
若是该 port 是用来提供 dvr 服务的,则返回该 port 的 host_id 属性
若该 port 是用来提供 dvr 服务的,则检查该 port 是否准备迁移到一个 host 上,若是的话则返回该 host 的 Id
- 调用
_get_snat_sync_interfaces
获取用于提供 snat 服务的 port 的数据信息 - 为所有的 router 数据填充
_snat_router_interfaces
属性
获取用于提供 snat 服务的 port 的数据信息
- 为 router 添加
_floatingips
属性。 - 若该 router 为 distributed,则需要判断 floating ip 的 host 属性是否与
host
一致 - 为 router 添加
_floatingip_agent_interfaces
属性。 - 调用
_get_fip_sync_interfaces
获取属于 agent 的floatingip_agent_gateway
的 Port
获取属于 agent 的 floatingip_agent_gateway
的 Port
def remove_unbound_allowed_address_pair_port_binding(self, context, service_port_dict, port_address_pairs, address_pair_port=None)
- 若是
address_pair_port
参数为空,则调用_get_address_pair_active_port_with_fip
是否有 port 与address_pair_port
中的ip_address
绑定 - 若存在与之绑定的 port,则会调用
core_plugin.update_port
更新这个 port 的一些信息(删除该 port 与 service_port 的相关联信息)
- 解析:
- port 的
allowed_address_pairs
属性可以让 port 有多个 ip 地址,并且这些 ip 地址都可以访问网络 - 这种场景常常用于 ha 的部署中
若 port 的 allowed_address_pairs
中的 ip_address 是一个 floating ip,则通过调用 core_plugin.get_port
获取与该 floating ip 绑定的 port
- 获取该 port 的
allowed_address_pairs
属性 - 获取
allowed_address_pairs
属性中的ip_address
数据 - 根据 ip address 获取其所在的 subnet
- 调用
_should_update_arp_entry_for_dvr_service_port
判断该 prot 需要调整 arp 记录 - 若
fixed_ips_to_delete
不空,则调用_get_allowed_address_pair_fixed_ips
获取 Port 的allowed_address_pairs
以及 port 本身的 ip 作为fixed_ips_to_delete
- 对于
fixed_ips_to_delete
中的记录,调用_generate_arp_table_and_notify_agent
通知 l3 agent 删除 arp 记录
def _should_update_arp_entry_for_dvr_service_port(self, port_dict):
# Check this is a valid VM or service port
return (n_utils.is_dvr_serviced(port_dict['device_owner']) and
port_dict['fixed_ips'])
通知 l3 agent 删除相应的 arp 记录
查询数据库 FloatingIP
获取该 port 的 floating ip
- 调用
_get_floatingip_on_port
获取 port 上的 floating ip - 调用
create_fip_agent_gw_port_if_not_exists
检查该 floating ip 所在网络是否在该 agent 上存在网关,若不存在则创建一个
- 调用
_get_agent_by_type_and_host
获取 host 上的 l3 agent 实例 - 调用
_get_agent_gw_ports_exist_for_network
检查 l3 agent 上是否存在为 network 提供网关服务的 port - 若有网关 port,调用
core_plugin.create_port
创建网关 port - 创建网关 port 成功后,调用
L3_NAT_dbonly_mixin._populate_mtu_and_subnets_for_ports
完善网关 port 的相关信息 - 若本来就存在网关 port,同样调用
L3_NAT_dbonly_mixin._populate_mtu_and_subnets_for_ports
完善网关 port 的相关信息
检查 l3 agent 上是否存在为 network 提供网关服务的 port
def update_unbound_allowed_address_pair_port_binding(self, context, service_port_dict, port_address_pairs, address_pair_port=None)
- 若是
address_pair_port
参数为空,则调用_get_address_pair_active_port_with_fip
是否有 port 与address_pair_port
中的ip_address
绑定 - 调用
core_plugin.update_port
更新 floating ip 原 port 的数据
- 调用
_should_update_arp_entry_for_dvr_service_port
判断该 prot 需要调整 arp 记录 - 若
fixed_ips_to_delete
不空,则调用_get_allowed_address_pair_fixed_ips
获取 Port 的allowed_address_pairs
以及 port 本身的 ip 作为fixed_ips_to_delete
- 调用
_generate_arp_table_and_notify_agent
生成 ARP 数据,并发送 RPC 通知
重写 L3_NAT_dbonly_mixin._create_router_db
方法,增加了处理 dvr 服务的功能
- 调用
L3_NAT_dbonly_mixin._create_router_db
创建Router
数据库记录 - 调用
is_distributed_router
判断该 router 是否为 distributed router - 调用
_process_extra_attr_router_create
创建与该 router 相关联的RouterExtraAttributes
数据库记录 - 返回处理后的 router 数据
重写 L3_NAT_dbonly_mixin._update_router_db
方法,增加了处理 dvr 服务的功能
- 调用
L3_NAT_dbonly_mixin._update_router_db
更新 Router 数据库的记录 - 判断 router 是否由非 distributed 更新为 distributed
- 调用
_validate_router_migration
验证 router 的 distributed 属性转变是否合法 - 更新 router 的
extra_attributes
属性 - 若更新的数据中
distributed
属性为 True 的话,则调用L3_NAT_dbonly_mixin._migrate_router_ports
更新 router 上 port 的 device_owner 为 dvr interface - 若 router 是否由非 distributed 更新为 distribute,则:
- 若更新后的 router 存在
gw_port_id
属性,则调用_create_snat_intf_ports_if_not_exists
获取该 router 上提供 snat 服务的 port,若没有则创建 - 调用
list_l3_agents_hosting_router
获取与该 router 绑定的 l3 agent 数据,然后调用_unbind_router
将 router 与这些 l3 agent 解除绑定
两件事:
- 每个 router (该 router 含有 gateway port)上有几个 subnet,则会有几个 snat port
- distributed router 不会与任何的 l3 agent 绑定
- 将一个 distributed router 更新至非 distributed router 是不合法的
- 只有在 router 的 admin_state_up 属性为 False 的情况下才可以将 router 由非 distributed 转化为 distributed
- 调用
_get_snat_interface_ports_for_router
获取 router 上提供 snat 服务的 port 的数据 - 若存在提供 snat 服务的 port,则调用
L3_NAT_dbonly_mixin._populate_mtu_and_subnets_for_ports
完善网关 port 的相关信息,然后直接退出 - 若不存在提供 snat 服务的 port:
- 获取该 router 是提供 dvr 服务的 port
- 调用
_add_csnat_router_interface_port
为 router 上所有的子网创建都创建一个提供 snat 服务的 port - 调用
_populate_mtu_and_subnets_for_ports
完善新创建的 snat port 的信息
查询 RouterPort
数据库记录,获取 router 上提供 snat 服务的 port 的数据
- 调用
create_port.create_port
创建一个提供 snat 服务的 port - 创建一个提供 snat 服务的
RouterPort
数据库记录 - 调用
_populate_mtu_and_subnets_for_ports
完善提供 snat 服务的 port 的信息
- 获取当前 router 上 gateway Port 所在的 network(也就是该router所绑定的 external network)
- 调用
L3_NAT_dbonly_mixin._delete_current_gw_port
删除 gateway port 数据 - 若 router 为 distributed router,且 router 的 external network 发生了变化:
- 调用
delete_csnat_router_interface_ports
删除所有的 snat port - 调用
core_plugin.get_ports
获取该 router 的 gateway port - 若不存在属于 external network 的 router gateway port:
- 调用
delete_floatingip_agent_gateway_port
删除该 host 上的属于该 external network 的 agent gateway port - 调用
l3_rpc_notifier.delete_fipnamespace_for_ext_net
通知删除该 host 上的属于 external network 的 fip namespace
- 获取 router 上提供 snat 服务的 port
- 调用
core_plugin.get_ports
获取这些 port 的数据 - 若 subnet_ids 为空,则删除所有 port
- 若 port 没有绑定 ip 则删除
- 若 subnet_ids 不为空,则删除与 subnet id 一致的 port
- 调用
core_plugin.get_ports
获取属于 externel network 的 aget gateway port - 调用
core_plugin.ipam.delete_port
删除那些没有绑定 host 或者 host 与 host_id 一致的 agent gateway port
- 调用
L3_NAT_dbonly_mixin._create_gw_port
为 router 创建 gateway port - 若 router 为 distributed router 且存在 gateway port,则调用
_create_snat_intf_ports_if_not_exists
获取该 router 上提供 snat 服务的 port,若没有则创建
返回 router 的 device_owner 属性
在 L3_NAT_dbonly_mixin._get_device_owner
的基础上增加了处理 distributed router 的属性
通过查询数据库 Port
和 AllowedAddressPair
获取 network_id 上 port 的 allowed_address_pairs
属性为 fixed_ip 的 port
- 调用
L3_NAT_dbonly_mixin._create_floatingip
创建 floating ip - 调用
_notify_floating_ip_change
发送 floating ip 更新引起的 router 更新的消息
- 获取 floating ip 绑定的 router 和 port
- 调用
_get_router
获取 router 数据 - 若 router 是 distributed router,则:
- 调用
_get_dvr_service_port_hostid
获取 port 所在的 host - 调用
_get_dvr_migrating_service_port_hostid
获取提供 dvr 服务的 port 准备迁移到的 host 的 id - 调用
l3_rpc_notifier.routers_updated_on_host
发送到原 host 上,router 的更新消息 - 若 port 确实准备迁移,则调用
l3_rpc_notifier.routers_updated_on_host
通知新的 host 上有 router 更新的消息 - 若 router 不是 distributed router,则调用
L3RpcNotifierMixin.notify_router_updated
发送 router 更新的消息
- 调用
_update_floatingip
完成 floating ip 的更新 - 调用
_notify_floating_ip_change
发送 floating ip 更新引起的 router 更新的 RPC 消息 - 若 floating ip 绑定的 router 或者 port 发生了变化,也会调用
_notify_floating_ip_change
发送 floating ip 更新的 RPC 消息
- 调用
_delete_floatingip
完成 floating ip 的删除工作 - 调用
_notify_floating_ip_change
发送 floating ip 删除引起的 RPC 更新的消息
- 调用
L3_NAT_dbonly_mixin._update_fip_assoc
完成 floating ip 数据的更新 - 若 floating ip 绑定了一个 internal port,则进行下面的操作:
- 获取该 floating ip 的 router,若 router 为 distributed,则调用
_get_dvr_service_port_hostid
检查该 port 是否需要 dvr 服务,若需要则返回该 port 绑定的 host - 若该 port 与某个 host 绑定,则调用
create_fip_agent_gw_port_if_not_exists
保证 agent gateway port 的存在 - 若该 port 没有与某个 host 绑定,则:
- 调用
core_plugin.get_port
获取 port 数据 - 调用
get_dvr_allowed_address_pair_device_owners
获取在 dvr 模式下,allowed_address_pair
port 的 device_owner - 若 port 的 device_owner 为空,或者该 port 绑定有
allowed_address_pair
属性,则: - 调用
_get_ports_for_allowed_address_pair_ip
获取该 network 上将此 ip 设置为allowed_address_pair
的 Port - 若有多个 port 的
allowed_address_pair
为该 floating ip 绑定的 ip,则不作处理 - 若只有一个 port 的
allowed_address_pair
为该 floating ip 绑定的 ip ,则调用_inherit_service_port_and_arp_update
更新 service port 数据,并发送 RPC 通知
- 调用
update_unbound_allowed_address_pair_port_binding
更新拥有allowed_address_pair
原 port(我们成为 service port) 的数据(host 和 device owner) - 调用
update_arp_entry_for_dvr_service_port
发送 service port 有关的 RPC 消息
- 调用
_validate_interface_info
验证 interface 的数据是否合法 - 调用
_get_router
获取路由信息 - 调用
_get_device_owner
获取路由的 device owner - 若是通过声明 port_id 来为 route 绑定 port,则:
- 调用
_check_router_port
检查 interface 数据,并发送 interface 将要创建的通知 - 调用
_add_interface_by_port
完成 port 和 router 的绑定 - 若是通过声明 subnet id 来直接为 router 添加 interface,则:
- 调用
_add_interface_by_subnet
完成 port 的创建 - 若 router 为 distributed 其 router 有 gateway port,则调用
_add_csnat_router_interface_port
在 router 上为该 port 所在的 subnet 创建一个提供 snat 服务的 port - 若是创建一个新 port,则:
- 创建一个
RouterPort
的数据库记录 - 调用
core_plugin.update_port
更新 port 数据,将 router 与 port 绑定 - 若是 subnet 是 ipv6,则:
- 调用
_find_v6_router_port_by_network_and_device_owner
找到该 router 上是否含有该 subnet 的 ipv6 地址的额port - 更新 port 数据,将 port 与 router 绑定
- 调用
_make_router_interface_info
获取 router interface 数据 - 调用
notify_router_interface_action
发送 router 更新的 RPC 消息以及通知消息 - 调用
registry.notify
发送 router interface after create 的通知 - 返回 router interface 的数据
若 csnat_port_check
为 True 且 该 port 为 snat port,则直接返回 false。
若不是则调用 L3_NAT_dbonly_mixin._port_has_ipv6_address
判断 port 是否含有 ipv6 地址
找到该 router 上是否含有该 subnet 的 ipv6 地址的额port
- 调用
_get_router
获取 router 数据 - 若该 router 不是 distributed router,则调用
L3_NAT_dbonly_mixin.remove_router_interface
完成 router interface 的创建 - 若该 router 是一个 distribiuted router,则:
- 调用
NeutronManager.get_service_plugins
获取 router plugin 实例 - 调用
plugin._get_dvr_hosts_for_router
获取删除该 router interface 前与该 router 绑定的 dvr host - 调用
L3_NAT_dbonly_mixin.remove_router_interface
删除该 router interface - 调用
plugin._get_dvr_hosts_for_router
获取删除该 router interface 后与该 router 绑定的 dvr host - 若是在删除 router interface 时,在某个 host 上移除了该 dvr router,则:
- 获取这些 host 上的 l3 agent
- 通过数据库
RouterL3AgentBinding
查询该 router 的绑定记录 - 若该 l3 agent 不是用来提供 snat 服务的,则调用
l3_rpc_notifier.router_removed_from_agent
发送 RPC 消息 - 调用
_check_for_multiprefix_csnat_port_and_update
检查该 router 的 snat port 是否含有该 subnet 的地址 - 若 snat port 中含有 subnet 的地址,则调用
delete_csnat_router_interface_ports
删除不用的 snat port - 返回被删除 router interface 的信息
- 若 router 包含 gateway port,则:
- 调用
_find_v6_router_port_by_network_and_device_owner
查询该 router 上是否含有该 network 的 ipv6 地址的额port - 若含有包含有 ipv6 地址的 port:
- 若该 port 不包含该 subnet 的 ip 地址,则不作任何处理
- 若不是,则调用
core_plugin.update_port
则在该 port 的 ip 地址中删除 subnet 下的地址 若 snat port 包含有 subnet 的 ip 地址,则返回 True
- 获取该 router 上 snat port
- 调用
core_plugin.get_ports
获取 port 的数据 - 若 snat port 不再含有 ip 地址,则调用
core_plugin.delete_port
删除该 snat port - 删除与 subnet 绑定的 snat port
根据 port 上的 fixed ip,获取该 ip 所在的 subnet