ML2 插件 create_network 函数主要完成的工作有:
第三步后续会介绍
create_network 函数的主干流程如下,主要功能就是将相关信息入库。
def create_network(self, context, network):
...
result, mech_context = self._create_network_db(context, network)
...
_create_network_db 函数的代码如下:
def _create_network_db(self, context, network):
...
with db_api.context_manager.writer.using(context):
net_db = self.create_network_db(context, network)
...
self.type_manager.create_network_segments(context, net_data,
tenant_id)
...
self._process_l3_create(context, result, net_data)
return result, mech_context
def create_network_db(self, context, network):
# single request processing
n = network['network']
with db_api.CONTEXT_WRITER.using(context):
args = {'tenant_id': n['tenant_id'],
'id': n.get('id') or uuidutils.generate_uuid(),
'name': n['name'],
'mtu': n.get('mtu'),
'admin_state_up': n['admin_state_up'],
'status': n.get('status', constants.NET_STATUS_ACTIVE),
'description': n.get('description')}
network = models_v2.Network(**args)
context.session.add(network)
if n['shared']:
np_rbac_args = {'project_id': network.project_id,
'object_id': network.id,
'action': 'access_as_shared',
'target_tenant': '*'}
np_rbac_obj = network_obj.NetworkRBAC(context, **np_rbac_args)
np_rbac_obj.create()
return network
这个函数做了两件事情:
n['shared'] 对应就是 Network 模型中的 shared 字段:一个布尔值,如果为 true,则表示这个网络可以被所有租户共享。
表 networkrbacs 表示网络操作权限,其中的 object_id 是外键,指向表 networks 中的主键 id;若字段 actions = ‘access_as_shared’ 表示 object_id 所代表的 Network是全租户共享的。
def _process_l3_create(self, context, net_data, req_data):
# external 对应 Network 模型中的 router:external 字段
external = req_data.get(extnet_apidef.EXTERNAL)
if external:
# 向表 externnetworks 添加记录
net_obj.ExternalNetwork(
context, network_id=net_data['id']).create()
net_rbac_args = {'project_id': net_data['tenant_id'],
'object_id': net_data['id'],
'action': 'access_as_external',
'target_tenant': '*'}
# 向表 networkrbacs 添加记录
net_obj.NetworkRBAC(context, **net_rbac_args).create()
net_data[extnet_apidef.EXTERNAL] = external
这段代码中的 external 就是 network model 中的 router: external 字段,当它等于 true 时, 表示这个网络是关联 Router 上的外部网络。
_create_network_db 函数主干流程的第三步是调用 self.type_manger.create_network_segments 函数。create_network_segments 代码如下:
def create_network_segments(self, context, network, tenant_id):
"""Call type drivers to create network segments."""
# 从传入的参数 network 中获取 segments
# 传入参数 network 是指用户调用网络的 RESTful API 传的参数
segments = self._process_provider_create(network)
with db_api.context_manager.writer.using(context):
# 如果传入参数中有 segments,则说明:
# (1)用户具备管理员权限(2)创建的是运营商拓展网络
network_id = network['id']
if segments:
for segment_index, segment in enumerate(segments):
# 调用 Type Driver 的 reserve_provider_segment 函数,将 segment 分配下来
segment = self.reserve_provider_segment(
context, segment)
self._add_network_segment(context, network_id, segment,
segment_index)
# 如果传入的是 Router 外部网关网络,并且配置了网络类型
elif (cfg.CONF.ml2.external_network_type and
self._get_attribute(network, extnet_apidef.EXTERNAL)):
segment = self._allocate_ext_net_segment(context)
self._add_network_segment(context, network_id, segment)
else:
segment = self._allocate_tenant_net_segment(context)
self._add_network_segment(context, network_id, segment)