Quantum-LinuxBridge插件-agent
本博客欢迎转发,但请保留原作者(@孔令贤HW)信息!内容系本人学习、研究和总结,如有雷同,实属荣幸!
1 初始化
文件:quantum/plugins/linuxbridge/agent/linuxbridge_quantum_agent.py
1.1 主函数
#============= ============主函数
defmain():
eventlet.monkey_patch()
cfg.CONF(args=sys.argv, project='quantum')
# (TODO) gary - swap with common logging
logging_config.setup_logging(cfg.CONF)
interface_mappings = {}
# agent使用的配置项
for mapping in cfg.CONF.LINUX_BRIDGE.physical_interface_mappings:
try:
physical_network, physical_interface = mapping.split(':')
# 更新字典信息,物理网络和物理接口的对应关系
interface_mappings[physical_network] = physical_interface
LOG.debug("physical network %s mapped to physical interface %s" %
(physical_network, physical_interface))
except ValueError as ex:
LOG.error("Invalid physical interface mapping: \'%s\' - %s" %
(mapping, ex))
sys.exit(1)
polling_interval = cfg.CONF.AGENT.polling_interval
reconnect_interval = cfg.CONF.DATABASE.reconnect_interval
root_helper = cfg.CONF.AGENT.root_helper
rpc = cfg.CONF.AGENT.rpc
# 如果在AGENT段配置了rpc
if rpc:
plugin = LinuxBridgeQuantumAgentRPC(interface_mappings,
polling_interval,
root_helper)
# 如果没有配置
else:
db_connection_url = cfg.CONF.DATABASE.sql_connection
plugin = LinuxBridgeQuantumAgentDB(interface_mappings,
polling_interval,
reconnect_interval,
root_helper,
db_connection_url)
LOG.info("Agent initialized successfully, now running... ")
# 主函数,内部是个循环
plugin.daemon_loop()
sys.exit(0)
1.2 使用的RPC类(接收和发送消息)
#============= ============使用RPC的类
classLinuxBridgeQuantumAgentRPC:
def__init__(self, interface_mappings, polling_interval,
root_helper):
self.polling_interval = polling_interval
self.root_helper = root_helper
# 创建LinuxBridge对象
self.setup_linux_bridge(interface_mappings)
self.setup_rpc(interface_mappings.values())
defsetup_rpc(self, physical_interfaces):
if physical_interfaces:
# 获取网络接口的MAC地址
mac = utils.get_interface_mac(physical_interfaces[0])
else:
devices = ip_lib.IPWrapper(self.root_helper).get_devices(True)
if devices:
mac = utils.get_interface_mac(devices[0].name)
else:
LOG.error("Unable to obtain MAC of any device for agent_id")
exit(1)
# agent_id在每一个计算节点上应该是不同的
self.agent_id = '%s%s' % ('lb', (mac.replace(":", "")))
LOG.info("RPC agent_id: %s" % self.agent_id)
# topic='q-agent-notifier'
self.topic = topics.AGENT
# 创建一个RPC发送端,routing-key='q-plugin'
self.plugin_rpc = agent_rpc.PluginApi(topics.PLUGIN)
# RPC network init
self.context = context.RequestContext('quantum', 'quantum',
is_admin=False)
# Handle updates from service
self.callbacks = LinuxBridgeRpcCallbacks(self.context,
self.linux_br)
self.dispatcher = self.callbacks.create_rpc_dispatcher()
# Define the listening consumers for the agent
# 创建两个队列监听者
# routing-key分别是'q-agent-notifier-network-delete'和'q-agent-notifier-port-update'
consumers = [[topics.PORT, topics.UPDATE],
[topics.NETWORK, topics.DELETE]]
self.connection = agent_rpc.create_consumers(self.dispatcher,
self.topic,
consumers)
# pyudev库,驱动和硬件设备管理
self.udev = pyudev.Context()
# pyudev.Monitor是一个同步的设备事件监听器, connecting to the kernel daemon through netlink
monitor = pyudev.Monitor.from_netlink(self.udev)
# 过滤事件
monitor.filter_by('net')
1.3 循环处理
#============= ============agent的循环处理方法
defdaemon_loop(self):
sync = True
devices = set()
LOG.info("LinuxBridge Agent RPC Daemon Started!")
whileTrue:
start = time.time()
if sync:
LOG.info("Agent out of sync with plugin!")
devices.clear()
sync = False
# 使用pyudev库获取本机网络设备实时信息,如果与上次保存信息相同直接返回进行下一次循环
device_info = self.update_devices(devices)
# notify plugin about device deltas
if device_info:
LOG.debug("Agent loop has new devices!")
# If treat devices fails - indicates must resync with plugin
# 处理增加或删除设备信息的主函数<=== 重要!
sync = self.process_network_devices(device_info)
devices = device_info['current']
# sleep till end of polling interval
elapsed = (time.time() - start)
if (elapsed < self.polling_interval):
time.sleep(self.polling_interval - elapsed)
else:
LOG.debug("Loop iteration exceeded interval (%s vs. %s)!",
self.polling_interval, elapsed)
以新增设备为例:
1. 首先向上层查询新增设备信息
2. 根据设备的admin_state_up状态调用LinuxBridge对象方法
physical_interface = self.interface_mappings.get(physical_network)
ifnot physical_interface:
LOG.error("No mapping for physical network %s" %
physical_network)
returnFalse
# flat模式
if int(vlan_id) == lconst.FLAT_VLAN_ID:
self.ensure_flat_bridge(network_id, physical_interface)
# vlan模式
else:
# 为接口添加vlan并创建网桥(如果没有的话)
self.ensure_vlan_bridge(network_id, physical_interface,
vlan_id)
if utils.execute(['brctl', 'addif', bridge_name, tap_device_name],
root_helper=self.root_helper):
returnFalse
LOG.debug("Done adding device %s to bridge %s" % (tap_device_name,
bridge_name))
returnTrue
3. 如果是vlan类型网络
defensure_vlan_bridge(self, network_id, physical_interface, vlan_id):
"""Create a vlan and bridge unless they already exist."""
interface = self.ensure_vlan(physical_interface, vlan_id)
bridge_name = self.get_bridge_name(network_id)
self.ensure_bridge(bridge_name, interface)
return interface
2 消息处理
如下图,在LinuxBridge插件的agent中只接收两种消息的处理。
一个是删除network,另一个是更新port。
2.1 network_delete
defnetwork_delete(self, context, **kwargs):
LOG.debug("network_delete received")
network_id = kwargs.get('network_id')
# 获取逻辑网络对应的网桥名称,前缀"brq"
bridge_name = self.linux_br.get_bridge_name(network_id)
LOG.debug("Delete %s", bridge_name)
self.linux_br.delete_vlan_bridge(bridge_name)
defdelete_vlan_bridge(self, bridge_name):
# 调用命令查询网桥是否存在
if self.device_exists(bridge_name):
# 获取网桥上的所有接口(列举目录/sys/devices/virtual/net/${bridge_name}/brif/)
interfaces_on_bridge = self.get_interfaces_on_bridge(bridge_name)
for interface in interfaces_on_bridge:
# 通过命令删除接口
self.remove_interface(bridge_name, interface)
for physical_interface in self.interface_mappings.itervalues():
# 若是flat类型的网络
if physical_interface == interface:
# This is a flat network => return IP's from bridge to
# interface
ips, gateway = self.get_interface_details(bridge_name)
self.update_interface_ip_details(interface,
bridge_name,
ips, gateway)
else:
if interface.startswith(physical_interface):
# 调用命令删除接口上创建的vlan
self.delete_vlan(interface)
LOG.debug("Deleting bridge %s" % bridge_name)
if utils.execute(['ip', 'link', 'set', bridge_name, 'down'],
root_helper=self.root_helper):
return
# 删除网桥
if utils.execute(['brctl', 'delbr', bridge_name],
root_helper=self.root_helper):
return
LOG.debug("Done deleting bridge %s" % bridge_name)
else:
LOG.error("Cannot delete bridge %s, does not exist" % bridge_name)
2.2 port_update
defport_update(self, context, **kwargs):
LOG.debug("port_update received")
port = kwargs.get('port')
# 若操作状态为True,增加设备
if port['admin_state_up']:
vlan_id = kwargs.get('vlan_id')
# create the networking for the port
self.linux_br.add_interface(port['network_id'],
vlan_id,
port['id'])
# 删除设备
else:
bridge_name = self.linux_br.get_bridge_name(port['network_id'])
tap_device_name = self.linux_br.get_tap_device_name(port['id'])
self.linux_br.remove_interface(bridge_name, tap_device_name)
本博客欢迎转发,但请保留原作者(@孔令贤HW)信息!内容系本人学习、研究和总结,如有雷同,实属荣幸!
相关推荐
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,亲测可用
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
centos7下centos-release-openstack-pike
- 描述了 Quantum 如何利用插件架构来支持不同的网络后端,例如 Open vSwitch (OVS)、Linux Bridge 等。 - **OpenStack Networking 部署用例** - 介绍了 Quantum 在不同场景下的部署方式,包括单节点部署、多节点...
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装