fuel-web/nailgun/nailgun/test/integration/test_network_configuration.py

541 lines
21 KiB
Python

# -*- coding: utf-8 -*-
# Copyright 2013 Mirantis, 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 json
from mock import patch
from sqlalchemy.sql import not_
from nailgun.db.sqlalchemy.models import Cluster
from nailgun.db.sqlalchemy.models import NetworkGroup
from nailgun.network.manager import NetworkManager
from nailgun.test.base import BaseIntegrationTest
from nailgun.test.base import reverse
class TestNovaNetworkConfigurationHandlerMultinode(BaseIntegrationTest):
def setUp(self):
super(TestNovaNetworkConfigurationHandlerMultinode, self).setUp()
cluster = self.env.create_cluster(api=True)
self.cluster = self.db.query(Cluster).get(cluster['id'])
def test_get_request_should_return_net_manager_and_networks(self):
response = self.env.nova_networks_get(self.cluster.id)
data = json.loads(response.body)
cluster = self.db.query(Cluster).get(self.cluster.id)
self.assertEquals(data['net_manager'], self.cluster.net_manager)
for network_group in cluster.network_groups:
network = [i for i in data['networks']
if i['id'] == network_group.id][0]
keys = [
'network_size',
'name',
'amount',
'cluster_id',
'vlan_start',
'cidr',
'id']
for key in keys:
self.assertEquals(network[key], getattr(network_group, key))
def test_not_found_cluster(self):
resp = self.env.nova_networks_get(self.cluster.id + 999,
expect_errors=True)
self.assertEquals(404, resp.status_code)
def test_change_net_manager(self):
new_net_manager = {'net_manager': 'VlanManager'}
self.env.nova_networks_put(self.cluster.id, new_net_manager)
self.db.refresh(self.cluster)
self.assertEquals(
self.cluster.net_manager,
new_net_manager['net_manager'])
def test_change_dns_nameservers(self):
new_dns_nameservers = {
'dns_nameservers': {
"nameservers": [
"208.67.222.222",
"208.67.220.220"
]
}
}
self.env.nova_networks_put(self.cluster.id, new_dns_nameservers)
self.db.refresh(self.cluster)
self.assertEquals(
self.cluster.dns_nameservers,
new_dns_nameservers['dns_nameservers']['nameservers']
)
def test_refresh_mask_on_cidr_change(self):
response = self.env.nova_networks_get(self.cluster.id)
data = json.loads(response.body)
mgmt = [n for n in data['networks']
if n['name'] == 'management'][0]
cidr = mgmt['cidr'].partition('/')[0] + '/25'
mgmt['cidr'] = cidr
mgmt['network_size'] = 128
resp = self.env.nova_networks_put(self.cluster.id, data)
self.assertEquals(resp.status_code, 202)
task = json.loads(resp.body)
self.assertEquals(task['status'], 'ready')
self.db.refresh(self.cluster)
mgmt_ng = [ng for ng in self.cluster.network_groups
if ng.name == 'management'][0]
self.assertEquals(mgmt_ng.cidr, cidr)
self.assertEquals(mgmt_ng.netmask, '255.255.255.128')
def test_wrong_net_provider(self):
resp = self.app.put(
reverse(
'NeutronNetworkConfigurationHandler',
kwargs={'cluster_id': self.cluster.id}),
json.dumps({}),
headers=self.default_headers,
expect_errors=True
)
self.assertEquals(resp.status_code, 400)
self.assertEquals(
resp.body,
u"Wrong net provider - environment uses 'nova_network'"
)
def test_do_not_update_net_manager_if_validation_is_failed(self):
new_net_manager = {'net_manager': 'VlanManager',
'networks': [{'id': 500, 'vlan_start': 500}]}
self.env.nova_networks_put(self.cluster.id, new_net_manager,
expect_errors=True)
self.db.refresh(self.cluster)
self.assertNotEquals(
self.cluster.net_manager,
new_net_manager['net_manager'])
def test_network_group_update_changes_network(self):
network = self.db.query(NetworkGroup).filter(
not_(NetworkGroup.name == "fuelweb_admin")
).first()
self.assertIsNotNone(network)
new_vlan_id = 500 # non-used vlan id
new_nets = {'networks': [{'id': network.id,
'vlan_start': new_vlan_id}]}
resp = self.env.nova_networks_put(self.cluster.id, new_nets)
self.assertEquals(resp.status_code, 202)
self.db.refresh(network)
self.assertEquals(network.amount, 1)
self.assertEquals(network.vlan_start, 500)
def test_update_networks_and_net_manager(self):
network = self.db.query(NetworkGroup).filter(
not_(NetworkGroup.name == "fuelweb_admin")
).first()
new_vlan_id = 500 # non-used vlan id
new_net = {'net_manager': 'VlanManager',
'networks': [{'id': network.id, 'vlan_start': new_vlan_id}]}
self.env.nova_networks_put(self.cluster.id, new_net)
self.db.refresh(self.cluster)
self.db.refresh(network)
self.assertEquals(
self.cluster.net_manager,
new_net['net_manager'])
self.assertEquals(network.vlan_start, new_vlan_id)
def test_networks_update_fails_with_wrong_net_id(self):
new_nets = {'networks': [{'id': 500,
'vlan_start': 500}]}
resp = self.env.nova_networks_put(self.cluster.id, new_nets,
expect_errors=True)
self.assertEquals(202, resp.status_code)
task = json.loads(resp.body)
self.assertEquals(task['status'], 'error')
self.assertEquals(
task['message'],
'Invalid network ID: 500'
)
def test_admin_public_floating_untagged_others_tagged(self):
resp = self.env.nova_networks_get(self.cluster.id)
data = json.loads(resp.body)
for net in data['networks']:
if net['name'] in ('fuelweb_admin', 'public', 'floating'):
self.assertIsNone(net['vlan_start'])
else:
self.assertIsNotNone(net['vlan_start'])
def test_mgmt_storage_networks_have_no_gateway(self):
resp = self.env.nova_networks_get(self.cluster.id)
self.assertEquals(200, resp.status_code)
data = json.loads(resp.body)
for net in data['networks']:
if net['name'] in ['management', 'storage']:
self.assertIsNone(net['gateway'])
def test_management_network_has_gw(self):
net_meta = self.env.get_default_networks_metadata().copy()
mgmt = filter(lambda n: n['name'] == 'management',
net_meta['nova_network']['networks'])[0]
mgmt['use_gateway'] = True
mgmt['gateway'] = '192.168.0.1'
def get_new_networks_metadata():
return net_meta
self.env.get_default_networks_metadata = get_new_networks_metadata
cluster = self.env.create(
cluster_kwargs={},
nodes_kwargs=[{"pending_addition": True}]
)
resp = self.env.nova_networks_get(cluster['id'])
data = json.loads(resp.body)
mgmt = filter(lambda n: n['name'] == 'management',
data['networks'])[0]
self.assertEquals(mgmt['gateway'], '192.168.0.1')
strg = filter(lambda n: n['name'] == 'storage',
data['networks'])[0]
self.assertIsNone(strg['gateway'])
def test_management_network_gw_set_but_not_in_use(self):
net_meta = self.env.get_default_networks_metadata().copy()
mgmt = filter(lambda n: n['name'] == 'management',
net_meta['nova_network']['networks'])[0]
mgmt['gateway'] = '192.168.0.1'
self.assertEquals(mgmt['use_gateway'], False)
def get_new_networks_metadata():
return net_meta
self.env.get_default_networks_metadata = get_new_networks_metadata
cluster = self.env.create(
cluster_kwargs={},
nodes_kwargs=[{"pending_addition": True}]
)
resp = self.env.nova_networks_get(cluster['id'])
data = json.loads(resp.body)
for n in data['networks']:
if n['name'] in ('management', 'storage'):
self.assertIsNone(n['gateway'])
class TestNeutronNetworkConfigurationHandlerMultinode(BaseIntegrationTest):
def setUp(self):
super(TestNeutronNetworkConfigurationHandlerMultinode, self).setUp()
cluster = self.env.create_cluster(api=True,
net_provider='neutron',
net_segment_type='gre',
mode='ha_compact'
)
self.cluster = self.db.query(Cluster).get(cluster['id'])
def test_get_request_should_return_net_provider_segment_and_networks(self):
response = self.env.neutron_networks_get(self.cluster.id)
data = json.loads(response.body)
cluster = self.db.query(Cluster).get(self.cluster.id)
self.assertEquals(data['net_provider'],
self.cluster.net_provider)
self.assertEquals(data['net_segment_type'],
self.cluster.net_segment_type)
for network_group in cluster.network_groups:
network = [i for i in data['networks']
if i['id'] == network_group.id][0]
keys = [
'network_size',
'name',
'amount',
'cluster_id',
'vlan_start',
'cidr',
'id']
for key in keys:
self.assertEquals(network[key], getattr(network_group, key))
def test_get_request_should_return_vips(self):
response = self.env.neutron_networks_get(self.cluster.id)
data = json.loads(response.body)
self.assertIn('public_vip', data)
self.assertIn('management_vip', data)
def test_not_found_cluster(self):
resp = self.env.neutron_networks_get(self.cluster.id + 999,
expect_errors=True)
self.assertEquals(404, resp.status_code)
def test_refresh_mask_on_cidr_change(self):
response = self.env.neutron_networks_get(self.cluster.id)
data = json.loads(response.body)
mgmt = [n for n in data['networks']
if n['name'] == 'management'][0]
cidr = mgmt['cidr'].partition('/')[0] + '/25'
mgmt['cidr'] = cidr
mgmt['network_size'] = 128
resp = self.env.neutron_networks_put(self.cluster.id, data)
self.assertEquals(202, resp.status_code)
task = json.loads(resp.body)
self.assertEquals(task['status'], 'ready')
self.db.refresh(self.cluster)
mgmt_ng = [ng for ng in self.cluster.network_groups
if ng.name == 'management'][0]
self.assertEquals(mgmt_ng.cidr, cidr)
self.assertEquals(mgmt_ng.netmask, '255.255.255.128')
def test_do_not_update_net_segmentation_type(self):
resp = self.env.neutron_networks_get(self.cluster.id)
data = json.loads(resp.body)
data['neutron_parameters']['segmentation_type'] = 'vlan'
resp = self.env.neutron_networks_put(self.cluster.id, data,
expect_errors=True)
self.assertEquals(202, resp.status_code)
task = json.loads(resp.body)
self.assertEquals(task['status'], 'error')
self.assertEquals(
task['message'],
"Change of 'segmentation_type' is prohibited"
)
def test_network_group_update_changes_network(self):
resp = self.env.neutron_networks_get(self.cluster.id)
data = json.loads(resp.body)
network = self.db.query(NetworkGroup).get(data['networks'][0]['id'])
self.assertIsNotNone(network)
data['networks'][0]['vlan_start'] = 500 # non-used vlan id
resp = self.env.neutron_networks_put(self.cluster.id, data)
self.assertEquals(resp.status_code, 202)
self.db.refresh(network)
self.assertEquals(network.amount, 1)
self.assertEquals(network.vlan_start, 500)
def test_update_networks_fails_if_change_net_segmentation_type(self):
resp = self.env.neutron_networks_get(self.cluster.id)
data = json.loads(resp.body)
network = self.db.query(NetworkGroup).get(data['networks'][0]['id'])
self.assertIsNotNone(network)
data['networks'][0]['vlan_start'] = 500 # non-used vlan id
data['neutron_parameters']['segmentation_type'] = 'vlan'
resp = self.env.neutron_networks_put(self.cluster.id, data,
expect_errors=True)
self.assertEquals(202, resp.status_code)
task = json.loads(resp.body)
self.assertEquals(task['status'], 'error')
self.assertEquals(
task['message'],
"Change of 'segmentation_type' is prohibited"
)
def test_networks_update_fails_with_wrong_net_id(self):
new_nets = {'networks': [{'id': 500,
'name': 'new',
'vlan_start': 500}]}
resp = self.env.neutron_networks_put(self.cluster.id, new_nets,
expect_errors=True)
self.assertEquals(202, resp.status_code)
task = json.loads(resp.body)
self.assertEquals(task['status'], 'error')
self.assertEquals(
task['message'],
'Invalid network ID: 500'
)
def test_refresh_public_cidr_on_range_gw_change(self):
data = json.loads(self.env.neutron_networks_get(self.cluster.id).body)
publ = filter(lambda ng: ng['name'] == 'public', data['networks'])[0]
self.assertEquals(publ['cidr'], '172.16.0.0/24')
publ['gateway'] = '199.61.0.1'
publ['ip_ranges'] = [['199.61.0.11', '199.61.0.33'],
['199.61.0.55', '199.61.0.99']]
virt_nets = data['neutron_parameters']['predefined_networks']
virt_nets['net04_ext']['L3']['floating'] = ['199.61.0.111',
'199.61.0.122']
resp = self.env.neutron_networks_put(self.cluster.id, data)
self.assertEquals(202, resp.status_code)
task = json.loads(resp.body)
self.assertEquals(task['status'], 'ready')
self.db.refresh(self.cluster)
publ_ng = filter(lambda ng: ng.name == 'public',
self.cluster.network_groups)[0]
self.assertEquals(publ_ng.cidr, '199.61.0.0/24')
def test_refresh_public_cidr_on_netmask_change(self):
data = json.loads(self.env.neutron_networks_get(self.cluster.id).body)
publ = filter(lambda ng: ng['name'] == 'public', data['networks'])[0]
self.assertEquals(publ['cidr'], '172.16.0.0/24')
publ['netmask'] = '255.255.252.0'
resp = self.env.neutron_networks_put(self.cluster.id, data)
self.assertEquals(202, resp.status_code)
task = json.loads(resp.body)
self.assertEquals(task['status'], 'ready')
self.db.refresh(self.cluster)
publ_ng = filter(lambda ng: ng.name == 'public',
self.cluster.network_groups)[0]
self.assertEquals(publ_ng.cidr, '172.16.0.0/22')
def test_do_not_refresh_public_cidr_on_its_change(self):
data = json.loads(self.env.neutron_networks_get(self.cluster.id).body)
publ = filter(lambda ng: ng['name'] == 'public', data['networks'])[0]
self.assertEquals(publ['cidr'], '172.16.0.0/24')
publ['cidr'] = '199.61.39.160/28'
# it is OK as public CIDR is ignored and nothing else is changed
resp = self.env.neutron_networks_put(self.cluster.id, data)
self.assertEquals(202, resp.status_code)
task = json.loads(resp.body)
self.assertEquals(task['status'], 'ready')
self.db.refresh(self.cluster)
publ_ng = filter(lambda ng: ng.name == 'public',
self.cluster.network_groups)[0]
self.assertEquals(publ_ng.cidr, '172.16.0.0/24')
def test_admin_public_untagged_others_tagged(self):
resp = self.env.neutron_networks_get(self.cluster.id)
data = json.loads(resp.body)
for net in data['networks']:
if net['name'] in ('fuelweb_admin', 'public',):
self.assertIsNone(net['vlan_start'])
else:
self.assertIsNotNone(net['vlan_start'])
def test_mgmt_storage_networks_have_no_gateway(self):
resp = self.env.neutron_networks_get(self.cluster.id)
self.assertEquals(200, resp.status_code)
data = json.loads(resp.body)
for net in data['networks']:
if net['name'] in ['management', 'storage']:
self.assertIsNone(net['gateway'])
def test_management_network_has_gw(self):
net_meta = self.env.get_default_networks_metadata().copy()
mgmt = filter(lambda n: n['name'] == 'management',
net_meta['neutron']['networks'])[0]
mgmt['use_gateway'] = True
def get_new_networks_metadata():
return net_meta
self.env.get_default_networks_metadata = get_new_networks_metadata
cluster = self.env.create(
cluster_kwargs={'net_provider': 'neutron',
'net_segment_type': 'gre'},
nodes_kwargs=[{"pending_addition": True}]
)
resp = self.env.neutron_networks_get(cluster['id'])
data = json.loads(resp.body)
mgmt = filter(lambda n: n['name'] == 'management',
data['networks'])[0]
self.assertEquals(mgmt['gateway'], '192.168.0.1')
strg = filter(lambda n: n['name'] == 'storage',
data['networks'])[0]
self.assertIsNone(strg['gateway'])
class TestNovaNetworkConfigurationHandlerHA(BaseIntegrationTest):
def setUp(self):
super(TestNovaNetworkConfigurationHandlerHA, self).setUp()
cluster = self.env.create_cluster(api=True, mode='ha_compact')
self.cluster = self.db.query(Cluster).get(cluster['id'])
self.net_manager = NetworkManager
def test_returns_management_vip_and_public_vip(self):
resp = json.loads(self.env.nova_networks_get(self.cluster.id).body)
self.assertEquals(
resp['management_vip'],
self.net_manager.assign_vip(self.cluster.id, 'management'))
self.assertEquals(
resp['public_vip'],
self.net_manager.assign_vip(self.cluster.id, 'public'))
class TestAdminNetworkConfiguration(BaseIntegrationTest):
@patch('nailgun.db.sqlalchemy.fixman.settings.ADMIN_NETWORK', {
"cidr": "192.168.0.0/24",
"netmask": "255.255.255.0",
"size": "256",
"first": "192.168.0.129",
"last": "192.168.0.254"
})
def setUp(self):
super(TestAdminNetworkConfiguration, self).setUp()
self.cluster = self.env.create(
cluster_kwargs={
"api": True
},
nodes_kwargs=[
{"pending_addition": True, "api": True}
]
)
def test_netconfig_error_when_admin_cidr_match_other_network_cidr(self):
resp = self.env.nova_networks_get(self.cluster['id'])
nets = json.loads(resp.body)
resp = self.env.nova_networks_put(self.cluster['id'], nets,
expect_errors=True)
self.assertEquals(resp.status_code, 202)
task = json.loads(resp.body)
self.assertEquals(task['status'], 'error')
self.assertEquals(task['progress'], 100)
self.assertEquals(task['name'], 'check_networks')
self.assertIn("Address space intersection between networks:\n"
"admin (PXE), management.",
task['message'])
def test_deploy_error_when_admin_cidr_match_other_network_cidr(self):
resp = self.env.cluster_changes_put(self.cluster['id'],
expect_errors=True)
self.assertEquals(resp.status_code, 202)
task = json.loads(resp.body)
self.assertEquals(task['status'], 'error')
self.assertEquals(task['progress'], 100)
self.assertEquals(task['name'], 'deploy')
self.assertIn("Address space intersection between networks:\n"
"admin (PXE), management.",
task['message'])