Validate local_interface exists
In order to improve the user experiance, we should validate that the provided local_interface actually exists prior to trying to configure the undercloud with it. If net_config_override is not used and the local_interface does not exist, an error will be returned to the user early on in the installation process. Additionally if the user does not have an undercloud.conf, a warning is printed to show that the defaults will be used. Change-Id: Ia2a7e7fc916f6d2b62e212cb42641494b88d6d17 Closes-Bug: #1709177
This commit is contained in:
parent
88c3b8529b
commit
062346e319
|
@ -12,6 +12,8 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
|
||||
from oslo_config import fixture as config_fixture
|
||||
from oslotest import base
|
||||
|
||||
|
@ -25,7 +27,9 @@ class TestValidator(base.BaseTestCase):
|
|||
self.conf = config_fixture.Config()
|
||||
self.useFixture(self.conf)
|
||||
|
||||
def test_validation_passes(self):
|
||||
@mock.patch('netifaces.interfaces')
|
||||
def test_validation_passes(self, ifaces_mock):
|
||||
ifaces_mock.return_value = ['eth1']
|
||||
undercloud._validate_network()
|
||||
|
||||
def test_fail_on_local_ip(self):
|
||||
|
@ -122,7 +126,9 @@ class TestValidator(base.BaseTestCase):
|
|||
validator.validate_config(params, lambda x: None)
|
||||
self.assertEqual(save_params, params)
|
||||
|
||||
def test_valid_undercloud_nameserver_passes(self):
|
||||
@mock.patch('netifaces.interfaces')
|
||||
def test_valid_undercloud_nameserver_passes(self, ifaces_mock):
|
||||
ifaces_mock.return_value = ['eth1']
|
||||
self.conf.config(undercloud_nameservers=['192.168.24.4',
|
||||
'192.168.24.5'])
|
||||
undercloud._validate_network()
|
||||
|
@ -144,19 +150,44 @@ class TestValidator(base.BaseTestCase):
|
|||
self.assertRaises(validator.FailedValidation,
|
||||
undercloud._validate_network)
|
||||
|
||||
def test_ssl_hosts_allowed(self):
|
||||
@mock.patch('netifaces.interfaces')
|
||||
def test_ssl_hosts_allowed(self, ifaces_mock):
|
||||
ifaces_mock.return_value = ['eth1']
|
||||
self.conf.config(undercloud_public_host='public.domain',
|
||||
undercloud_admin_host='admin.domain',
|
||||
undercloud_service_certificate='foo.pem',
|
||||
enable_ui=False)
|
||||
undercloud._validate_network()
|
||||
|
||||
def test_allow_all_with_ui(self):
|
||||
@mock.patch('netifaces.interfaces')
|
||||
def test_allow_all_with_ui(self, ifaces_mock):
|
||||
ifaces_mock.return_value = ['eth1']
|
||||
self.conf.config(undercloud_admin_host='10.0.0.10',
|
||||
generate_service_certificate=True,
|
||||
enable_ui=True)
|
||||
|
||||
def test_fail_on_invalid_ip(self):
|
||||
@mock.patch('netifaces.interfaces')
|
||||
def test_fail_on_invalid_ip(self, ifaces_mock):
|
||||
ifaces_mock.return_value = ['eth1']
|
||||
self.conf.config(dhcp_start='foo.bar')
|
||||
self.assertRaises(validator.FailedValidation,
|
||||
undercloud._validate_network)
|
||||
|
||||
@mock.patch('netifaces.interfaces')
|
||||
def test_validate_interface_exists(self, ifaces_mock):
|
||||
ifaces_mock.return_value = ['eth0', 'eth1']
|
||||
self.conf.config(local_interface='eth0')
|
||||
undercloud._validate_network()
|
||||
|
||||
@mock.patch('netifaces.interfaces')
|
||||
def test_fail_validate_interface_missing(self, ifaces_mock):
|
||||
ifaces_mock.return_value = ['eth0', 'eth1']
|
||||
self.conf.config(local_interface='em1')
|
||||
self.assertRaises(validator.FailedValidation,
|
||||
undercloud._validate_network)
|
||||
|
||||
@mock.patch('netifaces.interfaces')
|
||||
def test_validate_interface_with_net_config_override(self, ifaces_mock):
|
||||
ifaces_mock.return_value = ['eth0', 'eth1']
|
||||
self.conf.config(local_interface='em2', net_config_override='foo')
|
||||
undercloud._validate_network()
|
||||
|
|
|
@ -550,6 +550,8 @@ def _load_config():
|
|||
conf_params += ['--config-file', PATHS.PASSWORD_PATH]
|
||||
if os.path.isfile(PATHS.CONF_PATH):
|
||||
conf_params += ['--config-file', PATHS.CONF_PATH]
|
||||
else:
|
||||
LOG.warning('%s does not exist. Using defaults.' % PATHS.CONF_PATH)
|
||||
CONF(conf_params)
|
||||
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
# under the License.
|
||||
|
||||
import netaddr
|
||||
import netifaces
|
||||
|
||||
|
||||
class FailedValidation(Exception):
|
||||
|
@ -35,6 +36,7 @@ def validate_config(params, error_callback):
|
|||
_validate_inspection_range(local_params, error_callback)
|
||||
_validate_no_overlap(local_params, error_callback)
|
||||
_validate_ips(local_params, error_callback)
|
||||
_validate_interface_exists(local_params, error_callback)
|
||||
|
||||
|
||||
def _validate_ips(params, error_callback):
|
||||
|
@ -143,3 +145,13 @@ def _validate_no_overlap(params, error_callback):
|
|||
(params['inspection_start'], params['inspection_end'],
|
||||
params['dhcp_start'], params['dhcp_end']))
|
||||
error_callback(message)
|
||||
|
||||
|
||||
def _validate_interface_exists(params, error_callback):
|
||||
"""Validate the provided local interface exists"""
|
||||
local_interface = params['local_interface']
|
||||
net_override = params['net_config_override']
|
||||
if not net_override and local_interface not in netifaces.interfaces():
|
||||
message = ('Invalid local_interface specified. %s is not available.' %
|
||||
local_interface)
|
||||
error_callback(message)
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
fixes:
|
||||
- |
|
||||
Validate the local_interface for the undercloud install to fail fast if
|
||||
the interface does not actually exist on the system. If net_config_override
|
||||
is configured, the local_interface will not be validated.
|
||||
- |
|
||||
Log a warning if undercloud.conf is missing to indicate that the defaults
|
||||
will be used.
|
|
@ -9,6 +9,7 @@ python-swiftclient>=3.2.0 # Apache-2.0
|
|||
oslo.config!=4.3.0,!=4.4.0,>=4.0.0 # Apache-2.0
|
||||
psutil>=3.2.2 # BSD
|
||||
netaddr!=0.7.16,>=0.7.13 # BSD
|
||||
netifaces>=0.10.4 # MIT
|
||||
pystache # MIT
|
||||
os-refresh-config # Apache-2.0
|
||||
os-apply-config # Apache-2.0
|
||||
|
|
Loading…
Reference in New Issue