deb-python-os-cloud-config/os_cloud_config/neutron.py
Steve Kowalik 9ea690d0d3 Do not hardcode datacentre as the physical network
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
2015-01-23 12:38:54 +11:00

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