9ea690d0d3
Currently, setup-neutron's net creation code sets the provider:physical_network property to 'datacentre' for VLAN'd networks. This is incorrect, and in fact is a (somewhat) obvious regression from the earlier VLAN code before the migration. Change-Id: I677f3de70980d1db8cf64c822ad10e07368f928e Closes-Bug: #1398457
151 lines
6.1 KiB
Python
151 lines
6.1 KiB
Python
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
# implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import logging
|
|
|
|
from os_cloud_config.cmd.utils import _clients as clients
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
def initialize_neutron(network_desc, neutron_client=None,
|
|
keystone_client=None):
|
|
if not neutron_client:
|
|
LOG.warn('Creating neutron client inline is deprecated, please pass '
|
|
'the client as parameter.')
|
|
neutron_client = clients.get_neutron_client()
|
|
if not keystone_client:
|
|
LOG.warn('Creating keystone client inline is deprecated, please pass '
|
|
'the client as parameter.')
|
|
keystone_client = clients.get_keystone_client()
|
|
|
|
admin_tenant = _get_admin_tenant_id(keystone_client)
|
|
if 'physical' in network_desc:
|
|
network_type = 'physical'
|
|
if not admin_tenant:
|
|
raise ValueError("No admin tenant registered in Keystone")
|
|
if not network_desc['physical']['metadata_server']:
|
|
raise ValueError("metadata_server is required for physical "
|
|
"networks")
|
|
elif 'float' in network_desc:
|
|
network_type = 'float'
|
|
else:
|
|
raise ValueError("No float or physical network defined.")
|
|
net = _create_net(neutron_client, network_desc, network_type, admin_tenant)
|
|
subnet = _create_subnet(neutron_client, net, network_desc, network_type,
|
|
admin_tenant)
|
|
if 'external' in network_desc:
|
|
router = _create_router(neutron_client, subnet)
|
|
ext_net = _create_net(neutron_client, network_desc, 'external', None)
|
|
_create_subnet(neutron_client, ext_net, network_desc, 'external', None)
|
|
neutron_client.add_gateway_router(
|
|
router['router']['id'], {'network_id': ext_net['network']['id']})
|
|
LOG.debug("Neutron configured.")
|
|
|
|
|
|
def _get_admin_tenant_id(keystone):
|
|
"""Fetch the admin tenant id from Keystone.
|
|
|
|
:param keystone: A keystone v2 client.
|
|
"""
|
|
LOG.debug("Discovering admin tenant.")
|
|
tenant = keystone.tenants.find(name='admin')
|
|
if tenant:
|
|
return tenant.id
|
|
|
|
|
|
def _create_net(neutron, network_desc, network_type, admin_tenant):
|
|
"""Create a new neutron net.
|
|
|
|
:param neutron: A neutron v2 client.
|
|
:param network_desc: A network description.
|
|
:param network_type: The type of network to create.
|
|
:param admin_tenant: The admin tenant id in Keystone.
|
|
"""
|
|
LOG.debug("Creating %s network." % network_type)
|
|
type_desc = network_desc[network_type]
|
|
network = {'admin_state_up': True,
|
|
'name': type_desc['name']}
|
|
if network_type == 'physical':
|
|
network.update({'tenant_id': admin_tenant,
|
|
'provider:network_type': 'flat',
|
|
'provider:physical_network': network['name']})
|
|
elif network_type == 'float':
|
|
network['shared'] = True
|
|
elif network_type == 'external':
|
|
network['router:external'] = True
|
|
if type_desc.get('segmentation_id'):
|
|
vlan_tag = type_desc['segmentation_id']
|
|
physical_network = type_desc['physical_network']
|
|
network.update({'provider:network_type': 'vlan',
|
|
'provider:segmentation_id': vlan_tag,
|
|
'provider:physical_network': physical_network})
|
|
return neutron.create_network({'network': network})
|
|
|
|
|
|
def _create_subnet(neutron, net, network_desc, network_type, admin_tenant):
|
|
"""Create a new neutron subnet.
|
|
|
|
:param neutron: A neutron v2 client.
|
|
:param network_desc: A network description.
|
|
:param network_type: The type of network to create.
|
|
:param admin_tenant: The admin tenant id in Keystone.
|
|
"""
|
|
type_desc = network_desc[network_type]
|
|
cidr = type_desc['cidr']
|
|
LOG.debug("Creating %s subnet, with CIDR %s." % (network_type, cidr))
|
|
subnet = {'ip_version': 4, 'network_id': net['network']['id'],
|
|
'cidr': cidr}
|
|
if network_type == 'physical':
|
|
metadata = network_desc['physical']['metadata_server']
|
|
subnet.update({'tenant_id': admin_tenant,
|
|
'host_routes': [{'destination': '169.254.169.254/32',
|
|
'nexthop': metadata}]})
|
|
elif network_type == 'external':
|
|
subnet['enable_dhcp'] = False
|
|
if type_desc.get('gateway'):
|
|
subnet['gateway_ip'] = type_desc['gateway']
|
|
if type_desc.get('extra_routes'):
|
|
routes = type_desc['extra_routes']
|
|
if 'host_routes' not in subnet:
|
|
subnet['host_routes'] = []
|
|
subnet['host_routes'].extend(routes)
|
|
if type_desc.get('nameserver'):
|
|
subnet['dns_nameservers'] = [type_desc['nameserver']]
|
|
elif network_type == 'float':
|
|
subnet['dns_nameservers'] = ['8.8.8.8']
|
|
if 'enable_dhcp' in type_desc:
|
|
subnet['enable_dhcp'] = type_desc['enable_dhcp']
|
|
if (type_desc.get('allocation_start') and
|
|
type_desc.get('allocation_end')):
|
|
allocation_start = type_desc['allocation_start']
|
|
allocation_end = type_desc['allocation_end']
|
|
subnet['allocation_pools'] = [{'start': allocation_start,
|
|
'end': allocation_end}]
|
|
return neutron.create_subnet({'subnet': subnet})
|
|
|
|
|
|
def _create_router(neutron, subnet):
|
|
"""Create a new neutron router.
|
|
|
|
:param neutron: A neutron v2 client.
|
|
:param subnet: The subnet id to route for.
|
|
"""
|
|
LOG.debug("Creating router.")
|
|
router = neutron.create_router({'router': {'name': 'default-router'}})
|
|
neutron.add_interface_router(router['router']['id'],
|
|
{'subnet_id': subnet['subnet']['id']})
|
|
return router
|