You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
280 lines
9.7 KiB
280 lines
9.7 KiB
# Copyright 2015 Red Hat, Inc. |
|
# |
|
# 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 os |
|
import tempfile |
|
from unittest import mock |
|
|
|
import yaml |
|
|
|
from tripleoclient.tests.v1.overcloud_netenv_validate import fakes |
|
from tripleoclient.v1 import overcloud_netenv_validate |
|
|
|
|
|
EMPTY_NETENV = """resource_registry: |
|
OS::TripleO::BlockStorage::Net::SoftwareConfig: /tmp/foo |
|
|
|
parameter_defaults: |
|
NeutronExternalNetworkBridge: "''" |
|
""" |
|
|
|
|
|
class TestValidateOvercloudNetenv(fakes.TestValidateOvercloudNetenv): |
|
|
|
def setUp(self): |
|
super(TestValidateOvercloudNetenv, self).setUp() |
|
|
|
# Get the command object to test |
|
self.cmd = overcloud_netenv_validate.ValidateOvercloudNetenv( |
|
self.app, None) |
|
|
|
def temporary_nic_config_file(self, bridges): |
|
nic_config = { |
|
'resources': { |
|
'OsNetConfigImpl': { |
|
'properties': { |
|
'config': { |
|
'str_replace': { |
|
'params': { |
|
'$network_config': { |
|
'network_config': bridges, |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
tmp = tempfile.NamedTemporaryFile(mode='w', delete=False) |
|
yaml.dump(nic_config, tmp) |
|
tmp.close() |
|
return tmp.name |
|
|
|
def test_cidr_no_overlapping_networks(self): |
|
networks = [ |
|
'172.17.0.0/24', |
|
'172.16.0.0/24', |
|
'172.17.1.0/24', |
|
'172.17.2.0/24', |
|
'10.1.2.0/24', |
|
] |
|
self.cmd.error_count = 0 |
|
self.cmd.check_cidr_overlap(networks) |
|
self.assertEqual(0, self.cmd.error_count) |
|
|
|
def test_cidr_overlapping_networks(self): |
|
networks = [ |
|
'172.17.1.0/24', |
|
'172.17.1.0/24', |
|
'10.1.2.0/24', |
|
] |
|
self.cmd.error_count = 0 |
|
self.cmd.check_cidr_overlap(networks) |
|
self.assertEqual(1, self.cmd.error_count) |
|
|
|
def test_cidr_nonnumerical_address(self): |
|
networks = [ |
|
'nonsense', |
|
] |
|
self.cmd.error_count = 0 |
|
self.cmd.check_cidr_overlap(networks) |
|
self.assertEqual(1, self.cmd.error_count) |
|
|
|
def test_cidr_address_outside_of_range(self): |
|
networks = [ |
|
'172.17.0.278/24', |
|
] |
|
self.cmd.error_count = 0 |
|
self.cmd.check_cidr_overlap(networks) |
|
self.assertEqual(1, self.cmd.error_count) |
|
|
|
def test_vlan_ids_unique(self): |
|
vlans = { |
|
'InternalApiNetworkVlanID': 201, |
|
'StorageNetworkVlanID': 202, |
|
'StorageMgmtNetworkVlanID': 203, |
|
'TenantNetworkVlanID': 204, |
|
'ExternalNetworkVlanID': 100, |
|
} |
|
self.cmd.error_count = 0 |
|
self.cmd.check_vlan_ids(vlans) |
|
self.assertEqual(0, self.cmd.error_count) |
|
|
|
def test_vlan_ids_duplicate(self): |
|
vlans = { |
|
'InternalApiNetworkVlanID': 201, |
|
'StorageNetworkVlanID': 202, |
|
'StorageMgmtNetworkVlanID': 203, |
|
'TenantNetworkVlanID': 202, # conflicts with StorageNetworkVlanID |
|
'ExternalNetworkVlanID': 100, |
|
} |
|
self.cmd.error_count = 0 |
|
self.cmd.check_vlan_ids(vlans) |
|
self.assertEqual(1, self.cmd.error_count) |
|
|
|
def test_allocation_pools_pairing_no_overlap(self): |
|
filedata = { |
|
'InternalApiNetCidr': '172.17.0.0/24', |
|
'StorageNetCidr': '172.18.0.0/24', |
|
'InternalApiAllocationPools': [ |
|
{'start': '172.17.0.10', 'end': '172.17.0.200'}], |
|
'StorageAllocationPools': [ |
|
{'start': '172.18.0.10', 'end': '172.18.0.200'}], |
|
} |
|
pools = { |
|
'InternalApiAllocationPools': [ |
|
{'start': '172.17.0.10', 'end': '172.17.0.200'}], |
|
'StorageAllocationPools': [ |
|
{'start': '172.18.0.10', 'end': '172.18.0.200'}], |
|
} |
|
self.cmd.error_count = 0 |
|
self.cmd.check_allocation_pools_pairing(filedata, pools) |
|
self.assertEqual(0, self.cmd.error_count) |
|
|
|
def test_allocation_pools_pairing_inverse_range(self): |
|
filedata = { |
|
'InternalApiNetCidr': '172.17.0.0/24', |
|
'StorageNetCidr': '172.18.0.0/24', |
|
'InternalApiAllocationPools': [ |
|
{'start': '172.17.0.200', 'end': '172.17.0.10'}], |
|
'StorageAllocationPools': [ |
|
{'start': '172.18.0.10', 'end': '172.18.0.200'}], |
|
} |
|
pools = { |
|
'InternalApiAllocationPools': [ |
|
{'start': '172.17.0.200', 'end': '172.17.0.10'}], |
|
'StorageAllocationPools': [ |
|
{'start': '172.18.0.10', 'end': '172.18.0.200'}], |
|
} |
|
self.cmd.error_count = 0 |
|
self.cmd.check_allocation_pools_pairing(filedata, pools) |
|
self.assertEqual(1, self.cmd.error_count) |
|
|
|
def test_allocation_pools_pairing_pool_outside_subnet(self): |
|
filedata = { |
|
'InternalApiNetCidr': '172.17.0.0/24', |
|
'InternalApiAllocationPools': [ |
|
{'start': '172.16.0.10', 'end': '172.16.0.200'}], |
|
} |
|
pools = { |
|
'InternalApiAllocationPools': [ |
|
{'start': '172.16.0.10', 'end': '172.16.0.200'}], |
|
} |
|
self.cmd.error_count = 0 |
|
self.cmd.check_allocation_pools_pairing(filedata, pools) |
|
self.assertEqual(1, self.cmd.error_count) |
|
|
|
def test_allocation_pools_pairing_invalid_cidr(self): |
|
filedata = { |
|
'InternalApiNetCidr': '172.17.0.298/24', |
|
'InternalApiAllocationPools': [ |
|
{'start': '172.17.0.10', 'end': '172.17.0.200'}], |
|
} |
|
pools = { |
|
'InternalApiAllocationPools': [ |
|
{'start': '172.17.0.10', 'end': '172.17.0.200'}], |
|
} |
|
self.cmd.error_count = 0 |
|
self.cmd.check_allocation_pools_pairing(filedata, pools) |
|
self.assertEqual(1, self.cmd.error_count) |
|
|
|
def test_allocation_pools_pairing_invalid_range(self): |
|
filedata = { |
|
'InternalApiNetCidr': '172.17.0.0/24', |
|
'InternalApiAllocationPools': [ |
|
{'start': '172.17.0.10', 'end': '172.17.0.287'}], |
|
} |
|
pools = { |
|
'InternalApiAllocationPools': [ |
|
{'start': '172.17.0.10', 'end': '172.17.0.287'}], |
|
} |
|
self.cmd.error_count = 0 |
|
self.cmd.check_allocation_pools_pairing(filedata, pools) |
|
self.assertEqual(1, self.cmd.error_count) |
|
|
|
def test_nic_nonexistent_path(self): |
|
self.cmd.error_count = 0 |
|
self.cmd.NIC_validate('OS::TripleO::Controller::Net::SoftwareConfig', |
|
'this file that not exist') |
|
self.assertEqual(1, self.cmd.error_count) |
|
|
|
def test_nic_valid_file(self): |
|
bridges = [{ |
|
'type': 'ovs_bridge', |
|
'name': 'br-storage', |
|
'members': [ |
|
{'type': 'interface', 'name': 'eth0'}, |
|
{'type': 'interface', 'name': 'eth1'}, |
|
{'type': 'ovs_bond', 'name': 'bond1'} |
|
], |
|
}] |
|
tmp = self.temporary_nic_config_file(bridges) |
|
self.cmd.error_count = 0 |
|
self.cmd.NIC_validate( |
|
'OS::TripleO::Controller::Net::SoftwareConfig', tmp) |
|
os.unlink(tmp) |
|
self.assertEqual(0, self.cmd.error_count) |
|
|
|
def test_nic_no_bond_too_many_interfaces(self): |
|
bridges = [{ |
|
'type': 'ovs_bridge', |
|
'name': 'br-storage', |
|
'members': [ |
|
{'type': 'interface', 'name': 'eth0'}, |
|
{'type': 'interface', 'name': 'eth1'}, |
|
], |
|
}] |
|
tmp = self.temporary_nic_config_file(bridges) |
|
self.cmd.error_count = 0 |
|
self.cmd.NIC_validate( |
|
'OS::TripleO::Controller::Net::SoftwareConfig', tmp) |
|
os.unlink(tmp) |
|
self.assertEqual(1, self.cmd.error_count) |
|
|
|
def test_nic_two_bonds(self): |
|
bridges = [{ |
|
'type': 'ovs_bridge', |
|
'name': 'br-storage', |
|
'members': [ |
|
{'type': 'interface', 'name': 'eth0'}, |
|
{'type': 'interface', 'name': 'eth1'}, |
|
{'type': 'ovs_bond', 'name': 'bond1'}, |
|
{'type': 'ovs_bond', 'name': 'bond2'}, |
|
], |
|
}] |
|
tmp = self.temporary_nic_config_file(bridges) |
|
self.cmd.error_count = 0 |
|
self.cmd.NIC_validate( |
|
'OS::TripleO::Controller::Net::SoftwareConfig', tmp) |
|
os.unlink(tmp) |
|
self.assertEqual(1, self.cmd.error_count) |
|
|
|
@mock.patch('tripleoclient.v1.overcloud_netenv_validate.' |
|
'ValidateOvercloudNetenv.NIC_validate', autospec=True) |
|
def test_command(self, mock_nic_validate): |
|
"""Testing the command with a minimal file that will fail""" |
|
with tempfile.NamedTemporaryFile('wt') as net_file: |
|
net_file.write(EMPTY_NETENV) |
|
net_file.flush() |
|
|
|
arglist = ['--file', net_file.name] |
|
verifylist = [ |
|
('netenv', net_file.name), |
|
] |
|
|
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
|
# Validating a minimal file shouldn't raise errors. |
|
self.cmd.take_action(parsed_args)
|
|
|