1.命令行以及代码解析
neutron net-create public --shared --provider:physical_network public
--provider:network_type flat
如果是vlan,还需要加上segment_id
neutron net-create public --shared --provider:physical_network public
--provider:network_type vlan --provider:segmentation_id 110
当然, 如果你是vxlan,命令行需要这么敲:
https://www.server-world.info/en/note?os=CentOS_7&p=openstack_pike&f=20
注意,这个是没有physical_network的!!,然后segmentation_id也是数据库自己给的
# create internal network
[root@dlp ~(keystone)]# openstack network create int_net --provider-network-type vxlan
+---------------------------+--------------------------------------+
| Field | Value |
+---------------------------+--------------------------------------+
| admin_state_up | UP |
| availability_zone_hints | |
| availability_zones | |
| created_at | 2017-09-06T07:49:58Z |
| description | |
| dns_domain | None |
| id | b70e8cdc-8c61-4a3b-8dfc-060cba8f82f9 |
| ipv4_address_scope | None |
| ipv6_address_scope | None |
| is_default | False |
| is_vlan_transparent | None |
| mtu | 1450 |
| name | int_net |
| port_security_enabled | True |
| project_id | 09158bee8c6441519bf3a3743d936566 |
| provider:network_type | vxlan |
| provider:physical_network | None |
| provider:segmentation_id | 89 |
| qos_policy_id | None |
| revision_number | 2 |
| router:external | Internal |
| segments | None |
| shared | False |
| status | ACTIVE |
| subnets | |
| tags | |
| updated_at | 2017-09-06T07:49:58Z |
+---------------------------+--------------------------------------+
如果是创建外部网络 (provider-network,无论是vlan还是flat都是可以的)
[root@dlp ~(keystone)]# openstack network create \
--provider-physical-network physnet1 \
--provider-network-type flat --external ext_net
+---------------------------+--------------------------------------+
| Field | Value |
+---------------------------+--------------------------------------+
| admin_state_up | UP |
| availability_zone_hints | |
| availability_zones | |
| created_at | 2017-09-06T07:51:02Z |
| description | |
| dns_domain | None |
| id | e27d7f02-773f-4e11-8aa9-e70ebc05ab76 |
| ipv4_address_scope | None |
| ipv6_address_scope | None |
| is_default | False |
| is_vlan_transparent | None |
| mtu | 1500 |
| name | ext_net |
| port_security_enabled | True |
| project_id | 09158bee8c6441519bf3a3743d936566 |
| provider:network_type | flat |
| provider:physical_network | physnet1 |
| provider:segmentation_id | None |
| qos_policy_id | None |
| revision_number | 3 |
| router:external | External |
| segments | None |
| shared | False |
| status | ACTIVE |
| subnets | |
| tags | |
| updated_at | 2017-09-06T07:51:02Z |
+---------------------------+--------------------------------------+
看一看plugin:
def create_network(self, context, 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:
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.type_manager.reserve_provider_segment(session, segment)\
def reserve_provider_segment(self, session, segment):
network_type = segment.get(api.NETWORK_TYPE)
driver = self.drivers.get(network_type)
driver.obj.reserve_provider_segment(session, segment)
1.获取driver
2.执行reserve_provider_segment(session, segment)
看看type_vlan下面的driver:
def reserve_provider_segment(self, session, segment):
physical_network = segment[api.PHYSICAL_NETWORK]
vlan_id = segment[api.SEGMENTATION_ID]
with session.begin(subtransactions=True):
try:
alloc = (session.query(VlanAllocation).
filter_by(physical_network=physical_network,
vlan_id=vlan_id).
with_lockmode('update').
one())
if alloc.allocated:
raise exc.VlanIdInUse(vlan_id=vlan_id,
physical_network=physical_network)
LOG.debug(_("Reserving specific vlan %(vlan_id)s on physical "
"network %(physical_network)s from pool"),
{'vlan_id': vlan_id,
'physical_network': physical_network})
alloc.allocated = True
except sa.orm.exc.NoResultFound:
LOG.debug(_("Reserving specific vlan %(vlan_id)s on physical "
"network %(physical_network)s outside pool"),
{'vlan_id': vlan_id,
'physical_network': physical_network})
alloc = VlanAllocation(physical_network=physical_network,
vlan_id=vlan_id,
allocated=True)
session.add(alloc)
新的vlan_id应该是在数据库中不存在的,这样就可以直接在数据库中创建了
再看一看self.type_manager.allocate_tenant_segment(session):
def allocate_tenant_segment(self, session):
for network_type in self.tenant_network_types:
driver = self.drivers.get(network_type)
segment = driver.obj.allocate_tenant_segment(session)
if segment:
return segment
raise exc.NoNetworkAvailable()
def allocate_tenant_segment(self, session):
with session.begin(subtransactions=True):
alloc = (session.query(VlanAllocation).
filter_by(allocated=False).
with_lockmode('update').
first())
if alloc:
LOG.debug(_("Allocating vlan %(vlan_id)s on physical network "
"%(physical_network)s from pool"),
{'vlan_id': alloc.vlan_id,
'physical_network': alloc.physical_network})
alloc.allocated = True
return {api.NETWORK_TYPE: p_const.TYPE_VLAN,
api.PHYSICAL_NETWORK: alloc.physical_network,
api.SEGMENTATION_ID: alloc.vlan_id}
2.配置文件
https://www.server-world.info/en/note?os=CentOS_6&p=openstack_icehouse&f=16
[root@dlp ~(keystone)]# vi /etc/neutron/plugins/ml2/ml2_conf.ini
# line 36: add
[ml2_type_vlan]
network_vlan_ranges = physnet1:1000:2999
# add at the last line
[ovs]
tenant_network_type = vlan
bridge_mappings = physnet1:br-eth1
让我们看看这三个参数都有什么用,首先这三个都是很重要的配置文件
neutron\plugins\openvswitch\common\config.py:
DEFAULT_BRIDGE_MAPPINGS = []
DEFAULT_VLAN_RANGES = []
DEFAULT_TUNNEL_RANGES = []
DEFAULT_TUNNEL_TYPES = []
ovs_opts = [
cfg.StrOpt('integration_bridge', default='br-int',
help=_("Integration bridge to use")),
cfg.BoolOpt('enable_tunneling', default=False,
help=_("Enable tunneling support")),
cfg.StrOpt('tunnel_bridge', default='br-tun',
help=_("Tunnel bridge to use")),
cfg.StrOpt('int_peer_patch_port', default='patch-tun',
help=_("Peer patch port in integration bridge for tunnel "
"bridge")),
cfg.StrOpt('tun_peer_patch_port', default='patch-int',
help=_("Peer patch port in tunnel bridge for integration "
"bridge")),
cfg.StrOpt('local_ip', default='',
help=_("Local IP address of GRE tunnel endpoints.")),
cfg.ListOpt('bridge_mappings',
default=DEFAULT_BRIDGE_MAPPINGS,
help=_("List of <physical_network>:<bridge>")),
cfg.StrOpt('tenant_network_type', default='local',
help=_("Network type for tenant networks "
"(local, vlan, gre, vxlan, or none)")),
cfg.ListOpt('network_vlan_ranges',
default=DEFAULT_VLAN_RANGES,
help=_("List of <physical_network>:<vlan_min>:<vlan_max> "
"or <physical_network>")),
cfg.ListOpt('tunnel_id_ranges',
default=DEFAULT_TUNNEL_RANGES,
help=_("List of <tun_min>:<tun_max>")),
cfg.StrOpt('tunnel_type', default='',
help=_("The type of tunnels to use when utilizing tunnels, "
"either 'gre' or 'vxlan'")),
]
1.bridge_mappings = physnet1: br-eth1
def setup_physical_bridges(self, bridge_mappings):
'''Setup the physical network bridges.
Creates physical network bridges and links them to the
integration bridge using veths.
:param bridge_mappings: map physical network names to bridge names.
'''
self.phys_brs = {}
self.int_ofports = {}
self.phys_ofports = {}
ip_wrapper = ip_lib.IPWrapper(self.root_helper)
# 分成了physical_network 和 bridge
for physical_network, bridge in bridge_mappings.iteritems():
LOG.info(_("Mapping physical network %(physical_network)s to "
"bridge %(bridge)s"),
{'physical_network': physical_network,
'bridge': bridge})
# setup physical bridge
if not ip_lib.device_exists(bridge, self.root_helper):
LOG.error(_("Bridge %(bridge)s for physical network "
"%(physical_network)s does not exist. Agent "
"terminated!"),
{'physical_network': physical_network,
'bridge': bridge})
sys.exit(1)
br = ovs_lib.OVSBridge(bridge, self.root_helper) # 名字叫做br-eth1
br.remove_all_flows()
br.add_flow(priority=1, actions="normal")
self.phys_brs[physical_network] = br
# create veth to patch physical bridge with integration bridge
int_veth_name = self.get_veth_name(
constants.VETH_INTEGRATION_PREFIX, bridge)
self.int_br.delete_port(int_veth_name)
phys_veth_name = self.get_veth_name(
constants.VETH_PHYSICAL_PREFIX, bridge)
br.delete_port(phys_veth_name)
if ip_lib.device_exists(int_veth_name, self.root_helper):
ip_lib.IPDevice(int_veth_name, self.root_helper).link.delete()
# Give udev a chance to process its rules here, to avoid
# race conditions between commands launched by udev rules
# and the subsequent call to ip_wrapper.add_veth
utils.execute(['/sbin/udevadm', 'settle', '--timeout=10'])
int_veth, phys_veth = ip_wrapper.add_veth(int_veth_name,
phys_veth_name)
self.int_ofports[physical_network] = self.int_br.add_port(int_veth)
self.phys_ofports[physical_network] = br.add_port(phys_veth)
# block all untranslated traffic over veth between bridges
self.int_br.add_flow(priority=2,
in_port=self.int_ofports[physical_network],
actions="drop")
br.add_flow(priority=2,
in_port=self.phys_ofports[physical_network],
actions="drop")
# enable veth to pass traffic
int_veth.link.set_up()
phys_veth.link.set_up()
if self.veth_mtu:
# set up mtu size for veth interfaces
int_veth.link.set_mtu(self.veth_mtu)
phys_veth.link.set_mtu(self.veth_mtu)
2.network_vlan_ranges = physnet1:1000:2999