Merge "Fix checking of public IPs count"
This commit is contained in:
commit
f63dcb4f0e
@ -515,6 +515,23 @@ class Cluster(NailgunObject):
|
||||
def get_creds(cls, instance):
|
||||
return instance.attributes.editable['access']
|
||||
|
||||
@classmethod
|
||||
def should_assign_public_to_all_nodes(cls, instance):
|
||||
"""Determine whether Public network is to be assigned to all nodes in
|
||||
this cluster.
|
||||
|
||||
:param instance: cluster instance
|
||||
:returns: True when Public network is to be assigned to all nodes
|
||||
"""
|
||||
if instance.net_provider == \
|
||||
consts.CLUSTER_NET_PROVIDERS.nova_network:
|
||||
return True
|
||||
assignment = instance.attributes.editable.get(
|
||||
'public_network_assignment')
|
||||
if not assignment or assignment['assign_to_all_nodes']['value']:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class ClusterCollection(NailgunCollection):
|
||||
"""Cluster collection
|
||||
|
@ -152,12 +152,7 @@ class Node(NailgunObject):
|
||||
:param instance: Node DB instance
|
||||
:returns: True when node has Public network
|
||||
"""
|
||||
if instance.cluster.net_provider == \
|
||||
consts.CLUSTER_NET_PROVIDERS.nova_network:
|
||||
return True
|
||||
assignment = instance.cluster.attributes.editable.get(
|
||||
'public_network_assignment')
|
||||
if not assignment or assignment['assign_to_all_nodes']['value']:
|
||||
if Cluster.should_assign_public_to_all_nodes(instance.cluster):
|
||||
return True
|
||||
ctrl = set(['primary-controller', 'controller', 'zabbix-server'])
|
||||
if ctrl & (set(instance.roles) or set(instance.pending_roles)):
|
||||
@ -799,3 +794,7 @@ class NodeCollection(NailgunCollection):
|
||||
instances_ids = [instance.id for instance in instances]
|
||||
q = cls.filter_by_list(None, 'id', instances_ids, order_by='id')
|
||||
return cls.lock_for_update(q).all()
|
||||
|
||||
@classmethod
|
||||
def get_by_group_id(cls, group_id):
|
||||
return cls.filter_by(None, group_id=group_id)
|
||||
|
@ -575,7 +575,7 @@ class CheckBeforeDeploymentTask(object):
|
||||
cls._check_disks(task)
|
||||
cls._check_ceph(task)
|
||||
cls._check_volumes(task)
|
||||
cls._check_network(task)
|
||||
cls._check_public_network(task)
|
||||
|
||||
@classmethod
|
||||
def _check_nodes_are_online(cls, task):
|
||||
@ -687,17 +687,26 @@ class CheckBeforeDeploymentTask(object):
|
||||
(osd_count, osd_pool_size))
|
||||
|
||||
@classmethod
|
||||
def _check_network(cls, task):
|
||||
nodes_count = len(task.cluster.nodes)
|
||||
def _check_public_network(cls, task):
|
||||
all_public = \
|
||||
objects.Cluster.should_assign_public_to_all_nodes(task.cluster)
|
||||
|
||||
public_network = filter(
|
||||
public_networks = filter(
|
||||
lambda ng: ng.name == 'public',
|
||||
task.cluster.network_groups)[0]
|
||||
public_network_size = cls.__network_size(public_network)
|
||||
task.cluster.network_groups)
|
||||
|
||||
if public_network_size < nodes_count:
|
||||
error_message = cls.__format_network_error(nodes_count)
|
||||
raise errors.NetworkCheckError(error_message)
|
||||
for public in public_networks:
|
||||
nodes = objects.NodeCollection.get_by_group_id(public.group_id)
|
||||
if all_public:
|
||||
nodes_count = nodes.count()
|
||||
else:
|
||||
nodes_count = sum(int(objects.Node.should_have_public(node))
|
||||
for node in nodes)
|
||||
vip_count = 0 if not task.cluster.is_ha_mode else \
|
||||
int(any('controller' in node.all_roles for node in nodes))
|
||||
if cls.__network_size(public) < nodes_count + vip_count:
|
||||
error_message = cls.__format_network_error(public, nodes_count)
|
||||
raise errors.NetworkCheckError(error_message)
|
||||
|
||||
@classmethod
|
||||
def __network_size(cls, network):
|
||||
@ -705,9 +714,9 @@ class CheckBeforeDeploymentTask(object):
|
||||
for ip_range in network.ip_ranges)
|
||||
|
||||
@classmethod
|
||||
def __format_network_error(cls, nodes_count):
|
||||
return 'Not enough IP addresses. Public network must have at least '\
|
||||
'{nodes_count} IP addresses '.format(nodes_count=nodes_count) + \
|
||||
def __format_network_error(cls, public, nodes_count):
|
||||
return 'Not enough IP addresses. Public network {0} must have ' \
|
||||
'at least {1} IP addresses '.format(public.cidr, nodes_count) + \
|
||||
'for the current environment.'
|
||||
|
||||
|
||||
|
@ -1044,8 +1044,8 @@ class TestHandlers(BaseIntegrationTest):
|
||||
self.assertEqual(task.status, 'error')
|
||||
self.assertEqual(
|
||||
task.message,
|
||||
'Not enough IP addresses. Public network must have at least '
|
||||
'3 IP addresses for the current environment.')
|
||||
'Not enough IP addresses. Public network 172.16.0.0/24 must have '
|
||||
'at least 3 IP addresses for the current environment.')
|
||||
|
||||
def test_occurs_error_not_enough_ip_addresses(self):
|
||||
self.env.create(
|
||||
@ -1082,8 +1082,8 @@ class TestHandlers(BaseIntegrationTest):
|
||||
self.assertEqual(task.status, 'error')
|
||||
self.assertEqual(
|
||||
task.message,
|
||||
'Not enough IP addresses. Public network must have at least '
|
||||
'3 IP addresses for the current environment.')
|
||||
'Not enough IP addresses. Public network 220.0.1.0/24 must have '
|
||||
'at least 3 IP addresses for the current environment.')
|
||||
|
||||
def test_occurs_error_not_enough_free_space(self):
|
||||
meta = self.env.default_metadata()
|
||||
|
@ -234,10 +234,11 @@ class TestNodeObject(BaseIntegrationTest):
|
||||
attrs['public_network_assignment']['assign_to_all_nodes']['value'],
|
||||
False
|
||||
)
|
||||
self.assertFalse(
|
||||
objects.Cluster.should_assign_public_to_all_nodes(cluster))
|
||||
|
||||
nodes_w_public_count = 0
|
||||
for node in self.env.nodes:
|
||||
nodes_w_public_count += int(objects.Node.should_have_public(node))
|
||||
nodes_w_public_count = sum(int(objects.Node.should_have_public(node))
|
||||
for node in self.env.nodes)
|
||||
self.assertEqual(nodes_w_public_count, 2)
|
||||
|
||||
attrs['public_network_assignment']['assign_to_all_nodes']['value'] = \
|
||||
@ -250,10 +251,11 @@ class TestNodeObject(BaseIntegrationTest):
|
||||
headers=self.default_headers
|
||||
)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertTrue(
|
||||
objects.Cluster.should_assign_public_to_all_nodes(cluster))
|
||||
|
||||
nodes_w_public_count = 0
|
||||
for node in self.env.nodes:
|
||||
nodes_w_public_count += int(objects.Node.should_have_public(node))
|
||||
nodes_w_public_count = sum(int(objects.Node.should_have_public(node))
|
||||
for node in self.env.nodes)
|
||||
self.assertEqual(nodes_w_public_count, 5)
|
||||
|
||||
def test_removing_from_cluster(self):
|
||||
|
@ -19,8 +19,10 @@ from nailgun import consts
|
||||
from nailgun.db.sqlalchemy.models import Task
|
||||
from nailgun.errors import errors
|
||||
from nailgun import objects
|
||||
from nailgun.openstack.common import jsonutils
|
||||
from nailgun.task.task import CheckBeforeDeploymentTask
|
||||
from nailgun.test.base import BaseTestCase
|
||||
from nailgun.test.base import reverse
|
||||
from nailgun.volumes.manager import VolumeManager
|
||||
|
||||
|
||||
@ -163,6 +165,10 @@ class TestCheckBeforeDeploymentTask(BaseTestCase):
|
||||
def setUp(self):
|
||||
super(TestCheckBeforeDeploymentTask, self).setUp()
|
||||
self.env.create(
|
||||
cluster_kwargs={
|
||||
'net_provider': 'neutron',
|
||||
'net_segment_type': 'gre'
|
||||
},
|
||||
nodes_kwargs=[{'roles': ['controller']}])
|
||||
|
||||
self.env.create_node()
|
||||
@ -282,3 +288,71 @@ class TestCheckBeforeDeploymentTask(BaseTestCase):
|
||||
errors.NotEnoughControllers,
|
||||
CheckBeforeDeploymentTask._check_controllers_count,
|
||||
self.task)
|
||||
|
||||
def find_net_by_name(self, nets, name):
|
||||
for net in nets['networks']:
|
||||
if net['name'] == name:
|
||||
return net
|
||||
|
||||
def test_check_public_networks(self):
|
||||
cluster = self.env.clusters[0]
|
||||
self.env.create_nodes(
|
||||
2, api=True, roles=['controller'], cluster_id=cluster.id)
|
||||
self.env.create_nodes(
|
||||
2, api=True, roles=['compute'], cluster_id=cluster.id)
|
||||
# we have 3 controllers now
|
||||
self.assertEqual(
|
||||
sum('controller' in n.all_roles for n in self.env.nodes),
|
||||
3
|
||||
)
|
||||
|
||||
attrs = cluster.attributes.editable
|
||||
self.assertEqual(
|
||||
attrs['public_network_assignment']['assign_to_all_nodes']['value'],
|
||||
False
|
||||
)
|
||||
self.assertFalse(
|
||||
objects.Cluster.should_assign_public_to_all_nodes(cluster))
|
||||
|
||||
resp = self.env.neutron_networks_get(cluster.id)
|
||||
nets = resp.json_body
|
||||
|
||||
# enough IPs for 3 nodes but VIP
|
||||
self.find_net_by_name(nets, 'public')['ip_ranges'] = \
|
||||
[["172.16.0.2", "172.16.0.4"]]
|
||||
resp = self.env.neutron_networks_put(cluster.id, nets)
|
||||
self.assertEqual(resp.status_code, 202)
|
||||
|
||||
self.assertRaises(
|
||||
errors.NetworkCheckError,
|
||||
CheckBeforeDeploymentTask._check_public_network,
|
||||
self.task)
|
||||
|
||||
# enough IPs for 3 nodes and VIP
|
||||
self.find_net_by_name(nets, 'public')['ip_ranges'] = \
|
||||
[["172.16.0.2", "172.16.0.5"]]
|
||||
resp = self.env.neutron_networks_put(cluster.id, nets)
|
||||
self.assertEqual(resp.status_code, 202)
|
||||
|
||||
self.assertNotRaises(
|
||||
errors.NetworkCheckError,
|
||||
CheckBeforeDeploymentTask._check_public_network,
|
||||
self.task)
|
||||
|
||||
attrs['public_network_assignment']['assign_to_all_nodes']['value'] = \
|
||||
True
|
||||
resp = self.app.patch(
|
||||
reverse(
|
||||
'ClusterAttributesHandler',
|
||||
kwargs={'cluster_id': cluster.id}),
|
||||
params=jsonutils.dumps({'editable': attrs}),
|
||||
headers=self.default_headers
|
||||
)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertTrue(
|
||||
objects.Cluster.should_assign_public_to_all_nodes(cluster))
|
||||
|
||||
self.assertRaises(
|
||||
errors.NetworkCheckError,
|
||||
CheckBeforeDeploymentTask._check_public_network,
|
||||
self.task)
|
||||
|
Loading…
Reference in New Issue
Block a user