Delay creating external bridge until we are initializing

Previously, the snap set up a bridge using the default 10.20.20.0/24
network upon install. If there was a good reason not to use this
network (e.g., it already exists and is being used for another
purpose), MicroStack, and the host machine, could wind up in a broken
state.

This PR delays setting up the bridge until after we have given an
operator a chance to override the default settings.

This has been manually tested. To test, do the following:

1) Checkout the code, and run tox -e build
2) Run tools/make-a-microstack.sh
3) snapctl set config.network.ext-cidr and config.network.ext-gateway
4) Run microstack_init
5) Exit the snap shell and run microstack.launch

Change-Id: I9e268495f313b29d9781d80a2468fc0a1a450aa0
Closes-Bug: https://bugs.launchpad.net/microstack/+bug/1851521
This commit is contained in:
Pete Vander Giessen 2019-11-12 23:19:51 +00:00
parent 2f5847d6ad
commit c3ba4ee501
6 changed files with 92 additions and 46 deletions

10
snap-wrappers/init/wait-on-init Executable file
View File

@ -0,0 +1,10 @@
#!/bin/bash
set -e
if ! [ "$(snapctl get initialized)" == "true" ]; then
echo "Microstack not yet initliazed. Waiting to start."
exit 0;
fi
exec $@

View File

@ -209,7 +209,7 @@ apps:
# - network
external-bridge:
command: bin/setup-br-ex
command: wait-on-init setup-br-ex
daemon: oneshot
passthrough:
after: [ovs-vswitchd]
@ -419,6 +419,12 @@ parts:
organize:
openstack-wrapper: bin/openstack-wrapper
init-wrapper:
source: ./snap-wrappers/init
plugin: dump
organize:
wait-on-init: bin/wait-on-init
nova-config:
after: [openstack-projects]
plugin: dump

View File

@ -95,10 +95,8 @@ def main() -> None:
question_list = [
questions.Clustering(),
questions.Dns(),
questions.ExtGateway(),
questions.ExtCidr(),
questions.NetworkSettings(),
questions.OsPassword(), # TODO: turn this off if COMPUTE.
questions.IpForwarding(),
questions.ForceQemu(),
# The following are not yet implemented:
# questions.VmSwappiness(),

View File

@ -31,7 +31,7 @@ from init.shell import (check, call, check_output, shell, sql, nc_wait,
log_wait, restart, download)
from init.config import Env, log
from init.questions.question import Question
from init.questions import clustering
from init.questions import clustering, network
_env = Env().get_env()
@ -128,6 +128,7 @@ class ConfigQuestion(Question):
"""
check('snap-openstack', 'setup')
# TODO: get rid of this? (I think that it has become redundant)
mstackrc = '{SNAP_COMMON}/etc/microstack.rc'.format(**_env)
with open(mstackrc, 'r') as rc_file:
for line in rc_file.readlines():
@ -165,37 +166,24 @@ dnsmasq_dns_servers = {answer}
# started. Need to figure that out.
class ExtGateway(ConfigQuestion):
"""Possibly override default ext gateway."""
_type = 'string'
_question = 'External Gateway'
config_key = 'config.network.ext-gateway'
class NetworkSettings(Question):
"""Write network settings, and """
_type = 'auto'
_question = 'Network settings'
def yes(self, answer):
clustered = check_output('snapctl', 'get', 'config.clustered')
if clustered.lower() != 'true':
check('snapctl', 'set', 'config.network.control-ip={}'.format(
answer))
check('snapctl', 'set', 'config.network.compute-ip={}'.format(
answer))
_env['control_ip'] = _env['compute_ip'] = answer
else:
_env['control_ip'] = check_output('snapctl', 'get',
'config.network.control-ip')
_env['compute_ip'] = check_output('snapctl', 'get',
'config.network.compute-ip')
log.info('Configuring networking ...')
network.ExtGateway().ask()
network.ExtCidr().ask()
class ExtCidr(ConfigQuestion):
"""Possibly override the cidr."""
# Now that we have default or overriden values, setup the
# bridge and write all the proper values into our config
# files.
check('setup-br-ex')
check('snap-openstack', 'setup')
_type = 'string'
_question = 'External Ip Range'
config_key = 'config.network.ext-cidr'
def yes(self, answer):
_env['extcidr'] = answer
network.IpForwarding().ask()
class OsPassword(ConfigQuestion):
@ -209,20 +197,6 @@ class OsPassword(ConfigQuestion):
# TODO obfuscate the password!
class IpForwarding(Question):
"""Possibly setup IP forwarding."""
_type = 'boolean' # Auto for now, to maintain old behavior.
_question = 'Do you wish to setup ip forwarding? (recommended)'
config_key = 'config.host.ip-forwarding'
def yes(self, answer: str) -> None:
"""Use sysctl to setup ip forwarding."""
log.info('Setting up ipv4 forwarding...')
check('sysctl', 'net.ipv4.ip_forward=1')
class ForceQemu(Question):
_type = 'boolean'
config_key = 'config.host.check-qemu'

View File

@ -0,0 +1,52 @@
from init.config import Env, log
from init.questions.question import Question
from init.shell import check, check_output
_env = Env().get_env()
class ExtGateway(Question):
"""Possibly override default ext gateway."""
_type = 'string'
_question = 'External Gateway'
config_key = 'config.network.ext-gateway'
def yes(self, answer):
clustered = check_output('snapctl', 'get', 'config.clustered')
if clustered.lower() != 'true':
check('snapctl', 'set', 'config.network.control-ip={}'.format(
answer))
check('snapctl', 'set', 'config.network.compute-ip={}'.format(
answer))
_env['control_ip'] = _env['compute_ip'] = answer
else:
_env['control_ip'] = check_output('snapctl', 'get',
'config.network.control-ip')
_env['compute_ip'] = check_output('snapctl', 'get',
'config.network.compute-ip')
class ExtCidr(Question):
"""Possibly override the cidr."""
_type = 'string'
_question = 'External Ip Range'
config_key = 'config.network.ext-cidr'
def yes(self, answer):
_env['extcidr'] = answer
class IpForwarding(Question):
"""Possibly setup IP forwarding."""
_type = 'boolean' # Auto for now, to maintain old behavior.
_question = 'Do you wish to setup ip forwarding? (recommended)'
config_key = 'config.host.ip-forwarding'
def yes(self, answer: str) -> None:
"""Use sysctl to setup ip forwarding."""
log.info('Setting up ipv4 forwarding...')
check('sysctl', 'net.ipv4.ip_forward=1')

View File

@ -74,7 +74,7 @@ class Question():
raise InvalidQuestion(
'Invalid type {} specified'.format(self._type))
if self.config_key is None:
if self.config_key is None and self._type != 'auto':
raise InvalidQuestion(
"No config key specified. "
"We don't know how to load or save this question!")
@ -118,6 +118,9 @@ class Question():
operator specified settings during updates.
"""
if self._type == 'auto':
return
answer = shell.check_output(
'snapctl', 'get', '{key}'.format(key=self.config_key)
)
@ -144,6 +147,9 @@ class Question():
# By this time in the process 'yes' or 'no' answers will have
# been converted to booleans. Convert them to a lowercase
# 'true' or 'false' string for storage in the snapctl config.
if self._type == 'auto':
return
if self._type == 'boolean':
answer = str(answer).lower()