`
cloudtech
  • 浏览: 4617477 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

【openstack】Quantum-LinuxBridge插件-agent

 
阅读更多

Quantum-LinuxBridge插件-agent

1 初始化

文件:quantum/plugins/linuxbridge/agent/linuxbridge_quantum_agent.py

1.1 主函数

#============= ============主函数

def main():

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的类

class LinuxBridgeQuantumAgentRPC:

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())

def setup_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的循环处理方法

def daemon_loop(self):

sync = True

devices = set()

LOG.info("LinuxBridge Agent RPC Daemon Started!")

while True:

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)

if not physical_interface:

LOG.error("No mapping for physical network %s" %

physical_network)

return False

# 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):

return False

LOG.debug("Done adding device %s to bridge %s" % (tap_device_name,

bridge_name))

return True

3. 如果是vlan类型网络

def ensure_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

def network_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)

def delete_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

def port_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)

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics