Merge "Move ctlplane network/subnet setup to python"
This commit is contained in:
commit
9f53f0819b
|
@ -37,81 +37,6 @@ if [ -e /usr/sbin/getenforce ]; then
|
|||
fi
|
||||
fi
|
||||
|
||||
UNDERCLOUD_IP=$(os-apply-config --key local-ip --type netaddress)
|
||||
export UNDERCLOUD_IP
|
||||
|
||||
DHCP_START=$(os-apply-config --key neutron.dhcp_start --type netaddress)
|
||||
DHCP_END=$(os-apply-config --key neutron.dhcp_end --type netaddress)
|
||||
NETWORK_CIDR=$(os-apply-config --key neutron.network_cidr --type raw)
|
||||
NETWORK_GATEWAY=$(os-apply-config --key neutron.network_gateway --type netaddress)
|
||||
METADATA_SERVER=$UNDERCLOUD_IP
|
||||
PHYSICAL_NETWORK=ctlplane
|
||||
|
||||
# DHCP_START contains a ":" then assume a IPv6 subnet
|
||||
SUBNET_VERSION_STRING="--ip-version 4"
|
||||
SUBNET_ROUTE_STRING="--host-route destination=169.254.169.254/32,nexthop=$METADATA_SERVER"
|
||||
if [[ $DHCP_START =~ : ]] ; then
|
||||
SUBNET_VERSION_STRING="--ip-version 6 --ipv6-address-mode dhcpv6-stateless --ipv6-ra-mode dhcpv6-stateless"
|
||||
SUBNET_ROUTE_STRING=""
|
||||
fi
|
||||
|
||||
net_create=1
|
||||
ctlplane_id=$(neutron net-list -f csv -c id -c name --quote none | tail -n +2 | grep ctlplane | cut -d, -f 1)
|
||||
subnet_ids=$(neutron subnet-list -f csv -c id --quote none | tail -n +2)
|
||||
subnet_id=
|
||||
|
||||
for subnet_id in $subnet_ids; do
|
||||
network_id=$(neutron subnet-show -f value -c network_id $subnet_id)
|
||||
if [ "$network_id" = "$ctlplane_id" ]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$subnet_id" ]; then
|
||||
cidr=$(neutron subnet-show $subnet_id -f value -c cidr)
|
||||
# If the cidr's are equal, we can get by with just a network update
|
||||
if [ "$cidr" = "$NETWORK_CIDR" ]; then
|
||||
net_create=0
|
||||
neutron subnet-update $subnet_id \
|
||||
--allocation-pool start=$DHCP_START,end=$DHCP_END \
|
||||
--gateway $NETWORK_GATEWAY $SUBNET_ROUTE_STRING
|
||||
else
|
||||
echo "New cidr $NETWORK_CIDR does not equal old cidr $cidr"
|
||||
echo "Will attempt to delete and recreate subnet $subnet_id"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$net_create" -eq "1" ]; then
|
||||
# Delete the route, subnet and network to make sure it doesn't already exist
|
||||
if neutron router-show ctlplane-router ; then
|
||||
neutron router-interface-delete ctlplane-router ctlplane-subnet
|
||||
neutron router-delete ctlplane-router
|
||||
fi
|
||||
if neutron subnet-list | grep start; then
|
||||
neutron subnet-delete $(neutron subnet-list | grep start | awk '{print $2}')
|
||||
fi
|
||||
if neutron net-show ctlplane; then
|
||||
neutron net-delete ctlplane
|
||||
fi
|
||||
|
||||
neutron net-create ctlplane \
|
||||
--provider:network_type flat \
|
||||
--provider:physical_network ctlplane
|
||||
|
||||
neutron subnet-create --name ctlplane-subnet \
|
||||
--allocation-pool start=$DHCP_START,end=$DHCP_END \
|
||||
--gateway $NETWORK_GATEWAY \
|
||||
$SUBNET_VERSION_STRING $SUBNET_ROUTE_STRING \
|
||||
ctlplane $NETWORK_CIDR
|
||||
|
||||
# If ctlplane-subnet is IPv6 we need to start a router so the router advertisments are sent out
|
||||
# for statless IP addressing to work.
|
||||
if [[ $DHCP_START =~ : ]] ; then
|
||||
neutron router-create ctlplane-router
|
||||
neutron router-interface-add ctlplane-router ctlplane-subnet
|
||||
fi
|
||||
fi
|
||||
|
||||
# Disable nova quotas
|
||||
openstack quota set --cores -1 --instances -1 --ram -1 $(openstack project show admin | awk '$2=="id" {print $4}')
|
||||
|
||||
|
|
|
@ -773,6 +773,9 @@ class TestPostConfig(base.BaseTestCase):
|
|||
@mock.patch('os_client_config.make_client')
|
||||
@mock.patch('instack_undercloud.undercloud._migrate_to_convergence')
|
||||
@mock.patch('instack_undercloud.undercloud._ensure_node_resource_classes')
|
||||
@mock.patch(
|
||||
'instack_undercloud.undercloud._config_neutron_segments_and_subnets')
|
||||
@mock.patch('instack_undercloud.undercloud._ensure_neutron_network')
|
||||
@mock.patch('instack_undercloud.undercloud._member_role_exists')
|
||||
@mock.patch('instack_undercloud.undercloud._get_session')
|
||||
@mock.patch('ironicclient.client.get_client', autospec=True)
|
||||
|
@ -790,6 +793,8 @@ class TestPostConfig(base.BaseTestCase):
|
|||
mock_copy_stackrc, mock_delete, mock_mistral_client,
|
||||
mock_swift_client, mock_nova_client, mock_ir_client,
|
||||
mock_get_session, mock_member_role_exists,
|
||||
mock_ensure_neutron_network,
|
||||
mock_config_neutron_segments_and_subnets,
|
||||
mock_resource_classes, mock_migrate_to_convergence,
|
||||
mock_make_client):
|
||||
instack_env = {
|
||||
|
@ -1284,6 +1289,57 @@ class TestPostConfig(base.BaseTestCase):
|
|||
mock_cmce.assert_called_once_with(instack_env, mock_mistral)
|
||||
mock_create.assert_called_once_with(mock_mistral, ['hut8'])
|
||||
|
||||
def _neutron_mocks(self):
|
||||
mock_sdk = mock.MagicMock()
|
||||
mock_sdk.network.create_network = mock.Mock()
|
||||
mock_sdk.network.delete_segment = mock.Mock()
|
||||
mock_sdk.network.create_subnet = mock.Mock()
|
||||
mock_sdk.network.update_subnet = mock.Mock()
|
||||
return mock_sdk
|
||||
|
||||
def test_network_create(self):
|
||||
mock_sdk = self._neutron_mocks()
|
||||
mock_sdk.network.networks.return_value = iter([])
|
||||
segment_mock = mock.Mock()
|
||||
mock_sdk.network.segments.return_value = iter([segment_mock])
|
||||
undercloud._ensure_neutron_network(mock_sdk)
|
||||
mock_sdk.network.create_network.assert_called_with(
|
||||
name='ctlplane', provider_network_type='flat',
|
||||
provider_physical_network='ctlplane')
|
||||
|
||||
def test_network_exists(self):
|
||||
mock_sdk = self._neutron_mocks()
|
||||
mock_sdk.network.networks.return_value = iter(['ctlplane'])
|
||||
undercloud._ensure_neutron_network(mock_sdk)
|
||||
mock_sdk.network.create_network.assert_not_called()
|
||||
|
||||
def test_subnet_create(self):
|
||||
mock_sdk = self._neutron_mocks()
|
||||
host_routes = [{'destination': '169.254.169.254/32',
|
||||
'nexthop': '192.168.24.1'}]
|
||||
allocation_pool = [{'start': '192.168.24.5', 'end': '192.168.24.24'}]
|
||||
undercloud._neutron_subnet_create(mock_sdk, 'network_id',
|
||||
'192.168.24.0/24', '192.168.24.1',
|
||||
host_routes, allocation_pool,
|
||||
'ctlplane-subnet')
|
||||
mock_sdk.network.create_subnet.assert_called_with(
|
||||
name='ctlplane-subnet', cidr='192.168.24.0/24',
|
||||
gateway_ip='192.168.24.1', host_routes=host_routes, enable_dhcp=True,
|
||||
ip_version='4', allocation_pools=allocation_pool,
|
||||
network_id='network_id')
|
||||
|
||||
def test_subnet_update(self):
|
||||
mock_sdk = self._neutron_mocks()
|
||||
host_routes = [{'destination': '169.254.169.254/32',
|
||||
'nexthop': '192.168.24.1'}]
|
||||
allocation_pool = [{'start': '192.168.24.5', 'end': '192.168.24.24'}]
|
||||
undercloud._neutron_subnet_update(mock_sdk, 'subnet_id',
|
||||
'192.168.24.1', host_routes,
|
||||
allocation_pool, 'ctlplane-subnet')
|
||||
mock_sdk.network.update_subnet.assert_called_with(
|
||||
'subnet_id', name='ctlplane-subnet', gateway_ip='192.168.24.1',
|
||||
host_routes=host_routes, allocation_pools=allocation_pool)
|
||||
|
||||
|
||||
class TestUpgradeFact(base.BaseTestCase):
|
||||
@mock.patch('instack_undercloud.undercloud._run_command')
|
||||
|
|
|
@ -21,6 +21,7 @@ import glob
|
|||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
import netaddr
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
|
@ -111,7 +112,9 @@ log can be found at %(log_file)s.
|
|||
# We need 8 GB, leave a little room for variation in what 8 GB means on
|
||||
# different platforms.
|
||||
REQUIRED_MB = 7680
|
||||
|
||||
# Control plane network name
|
||||
PHYSICAL_NETWORK = 'ctlplane'
|
||||
CTLPLANE_SUBNET_NAME = 'ctlplane-subnet'
|
||||
|
||||
# When adding new options to the lists below, make sure to regenerate the
|
||||
# sample config by running "tox -e genconfig" in the project root.
|
||||
|
@ -1808,6 +1811,16 @@ def _post_config(instack_env, upgrade):
|
|||
ironic = ir_client.get_client(1, session=sess,
|
||||
os_ironic_api_version='1.21')
|
||||
|
||||
sdk = os_client_config.make_sdk(auth_url=auth_url,
|
||||
project_name=project,
|
||||
username=user,
|
||||
password=password,
|
||||
project_domain_name='Default',
|
||||
user_domain_name='Default')
|
||||
|
||||
network = _ensure_neutron_network(sdk)
|
||||
_config_neutron_segments_and_subnets(sdk, network.id)
|
||||
|
||||
_configure_ssh_keys(nova)
|
||||
_ensure_ssh_selinux_permission()
|
||||
_delete_default_flavors(nova)
|
||||
|
@ -1848,6 +1861,117 @@ def _post_config(instack_env, upgrade):
|
|||
_migrate_to_convergence(heat)
|
||||
|
||||
|
||||
def _ensure_neutron_network(sdk):
|
||||
try:
|
||||
network = list(sdk.network.networks(name=PHYSICAL_NETWORK))
|
||||
if not network:
|
||||
network = sdk.network.create_network(
|
||||
name=PHYSICAL_NETWORK, provider_network_type='flat',
|
||||
provider_physical_network=PHYSICAL_NETWORK)
|
||||
LOG.info("Network created %s", network)
|
||||
else:
|
||||
LOG.info("Not creating %s network, because it already exists.",
|
||||
PHYSICAL_NETWORK)
|
||||
network = network[0]
|
||||
except Exception as e:
|
||||
LOG.info("Network create/update failed %s", e)
|
||||
raise
|
||||
|
||||
return network
|
||||
|
||||
|
||||
def _neutron_subnet_create(sdk, network_id, cidr, gateway, host_routes,
|
||||
allocation_pool, name):
|
||||
try:
|
||||
# DHCP_START contains a ":" then assume a IPv6 subnet
|
||||
if ':' in allocation_pool[0]['start']:
|
||||
host_routes = ''
|
||||
subnet = sdk.network.create_subnet(
|
||||
name=name,
|
||||
cidr=cidr,
|
||||
gateway_ip=gateway,
|
||||
host_routes=host_routes,
|
||||
enable_dhcp=True,
|
||||
ip_version='6',
|
||||
ipv6_address_mode='dhcpv6-stateless',
|
||||
ipv6_ra_mode='dhcpv6-stateless',
|
||||
allocation_pools=allocation_pool,
|
||||
network_id=network_id)
|
||||
else:
|
||||
subnet = sdk.network.create_subnet(
|
||||
name=name,
|
||||
cidr=cidr,
|
||||
gateway_ip=gateway,
|
||||
host_routes=host_routes,
|
||||
enable_dhcp=True,
|
||||
ip_version='4',
|
||||
allocation_pools=allocation_pool,
|
||||
network_id=network_id)
|
||||
LOG.info("Subnet created %s", subnet)
|
||||
except Exception as e:
|
||||
LOG.error("Create subnet %s failed: %s", name, e)
|
||||
raise
|
||||
|
||||
return subnet
|
||||
|
||||
|
||||
def _neutron_subnet_update(sdk, subnet_id, gateway, host_routes,
|
||||
allocation_pool, name):
|
||||
try:
|
||||
# DHCP_START contains a ":" then assume a IPv6 subnet
|
||||
if ':' in allocation_pool[0]['start']:
|
||||
host_routes = ''
|
||||
subnet = sdk.network.update_subnet(
|
||||
subnet_id,
|
||||
name=name,
|
||||
gateway_ip=gateway,
|
||||
host_routes=host_routes,
|
||||
allocation_pools=allocation_pool)
|
||||
LOG.info("Subnet updated %s", subnet)
|
||||
except Exception as e:
|
||||
LOG.error("Update subnet %s failed: %s", name, e)
|
||||
raise
|
||||
|
||||
|
||||
def _ensure_neutron_router(sdk, name, subnet_id):
|
||||
try:
|
||||
router = sdk.network.create_router(name=name, admin_state_up='true')
|
||||
sdk.network.add_interface_to_router(router.id, subnet_id=subnet_id)
|
||||
except Exception as e:
|
||||
LOG.error("Create router for subnet %s failed: %s", name, e)
|
||||
raise
|
||||
|
||||
|
||||
def _get_subnet(sdk, cidr, network_id):
|
||||
try:
|
||||
subnet = list(sdk.network.subnets(cidr=cidr, network_id=network_id))
|
||||
except Exception:
|
||||
raise
|
||||
|
||||
return False if not subnet else subnet[0]
|
||||
|
||||
|
||||
def _config_neutron_segments_and_subnets(sdk, ctlplane_id):
|
||||
host_routes = [{'destination': '169.254.169.254/32',
|
||||
'nexthop': str(netaddr.IPNetwork(CONF.local_ip).ip)}]
|
||||
allocation_pool = [{'start': CONF.dhcp_start, 'end': CONF.dhcp_end}]
|
||||
|
||||
subnet = _get_subnet(sdk, CONF.network_cidr, ctlplane_id)
|
||||
if subnet:
|
||||
_neutron_subnet_update(sdk, subnet.id, CONF.network_gateway,
|
||||
host_routes, allocation_pool,
|
||||
CTLPLANE_SUBNET_NAME)
|
||||
else:
|
||||
subnet = _neutron_subnet_create(sdk, ctlplane_id, CONF.network_cidr,
|
||||
CONF.network_gateway, host_routes,
|
||||
allocation_pool, CTLPLANE_SUBNET_NAME)
|
||||
|
||||
# If the subnet is IPv6 we need to start a router so that router
|
||||
# advertisments are sent out for stateless IP addressing to work.
|
||||
if ':' in CONF.dhcp_start:
|
||||
_ensure_neutron_router(sdk, CTLPLANE_SUBNET_NAME, subnet.id)
|
||||
|
||||
|
||||
def _handle_upgrade_fact(upgrade=False):
|
||||
"""Create an upgrade fact for use in puppet
|
||||
|
||||
|
|
Loading…
Reference in New Issue