class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
external_net_db.External_net_db_mixin,
sg_db_rpc.SecurityGroupServerRpcMixin,
agentschedulers_db.DhcpAgentSchedulerDbMixin,
addr_pair_db.AllowedAddressPairsMixin,
extradhcpopt_db.ExtraDhcpOptMixin):
从Ml2Plugin的定义来看,它通过继承众多的Mixin,能够支持很多功能。由于具体设备的操作由Agent来完成,ML2 Plugin本身实际上大都是完成基于数据库的一些操作,致力于正确有效管理network/port/subnet这些资源及相互关系,同时正确地与Agent交互从而完成虚拟网络部署。类Ml2Plugin的众多基类中,除了SecurityGroupServerRpcMixin,其他都是与数据库操作相关。
除了三种核心的资源,ML2也支持许多扩展的资源,类Ml2Plugin需要实现这些资源的操作接口,以供收到用户请求时资源对应的Controller来调用。ML2支持的扩展资源在类Ml2Plugin里有定义:
_supported_extension_aliases = ["provider", "external-net", "binding",
"quotas", "security-group", "agent",
"dhcp_agent_scheduler",
"multi-provider", "allowed-address-pairs",
"extra_dhcp_opt"]
这些扩展资源里,并不是每一个的操作接口都是由类Ml2Plugin来实现,许多接口是由类Ml2Plugin所继承的父类提供的。比如对于security-group,就是由类SecurityGroupServerRpcMixin来提供操作接口。
举例:
创建一个名为public0的Flat类型的网络。
network创建无需通知Agent,所有流程限于ML2内部。
执行neutron的客户端命令创建网络,并开启debug模式,这可以让我们看到传递给Plugin的各个参数的生成过程。
$neutron net-create public01 –tenant_id 73fdsdflhsdfhdjfhd --provider:netwok_type flat –provider:physical_network physnet1 –debug
通过Router模块的路由,这个命令最终由Plugin的create_network()函数来完成。
#neutron/plugins/ml2/plugin.py
def create_network(self, context, network):
#从字典network中获取传递进来的参数
net_data = network['network']
segments = self._process_provider_create(net_data)
tenant_id = self._get_tenant_id_for_create(context, net_data)
session = context.session
with session.begin(subtransactions=True):
self._ensure_default_security_group(context, tenant_id)
#通过父类完成数据库模型的创建
result = super(Ml2Plugin, self).create_network(context, network)
network_id = result['id']
self._process_l3_create(context, result, net_data)
# REVISIT(rkukura): Consider moving all segment management
# to TypeManager.
if segments:
for segment in segments:
#通过Type Manager调用Type Driver的接口
self.type_manager.reserve_provider_segment(session,
segment)
db.add_network_segment(session, network_id, segment)
else:
segment = self.type_manager.allocate_tenant_segment(session)
db.add_network_segment(session, network_id, segment)
self._extend_network_dict_provider(context, result)
mech_context = driver_context.NetworkContext(self, context,
result)
#通过Mechanism Manger调用Mechanism Driver的precommit接口
self.mechanism_manager.create_network_precommit(mech_context)
try:
#通过Mechanism Manger调用Mechanism Driver的postcommit接口
self.mechanism_manager.create_network_postcommit(mech_context)
except ml2_exc.MechanismDriverError:
with excutils.save_and_reraise_exception():
LOG.error(_("mechanism_manager.create_network_postcommit "
"failed, deleting network '%s'"), result['id'])
self.delete_network(context, result['id'])
return result
因为命令执行时开启了debug模式,所以命令行很容易地获得字典network的内容。
Type Manager和Mechanisim Manager的接口定义方式不同,每个操作,Mechanisim Manager都有两个接口,一个在数据库session内调用,命名规则遵守“{action}-{object}-precommit”的形式,另外一个命名规则遵守“{action}-{object}-postcommit”的形式,而Type Manager的接口定义就没这么规整,比如上述代码的reserve_provider_segment()和_extend_network_dict_provider()