Use network roles data for assigning of VIPs

Additional information from VIPs description should be included into
VIPs data serialized for orchestrator in 7.0. It was correct in case of
using Neutron but it was not changed for Nova-Network case sinse 6.1.
NovaNetworkManager70 is introduced now and it provides the same VIPs
allocation as for NeutronManaget70 but without templates support.

Change-Id: Iddb1bb894e72084224a76d7de86c3ad57cf06b25
Closes-Bug: #1480202
This commit is contained in:
Aleksey Kasatkin 2015-08-04 08:22:11 +03:00
parent 3cf4de256d
commit 618a26a67e
8 changed files with 216 additions and 128 deletions

View File

@ -327,8 +327,6 @@ FUEL_GRANULAR_DEPLOY = '6.1'
FUEL_REMOTE_REPOS = '6.1'
# version of Fuel when external mongo was added
FUEL_EXTERNAL_MONGO = '6.1'
# version of Fuel when Nova is not supported anymore. Neutron is left only.
FUEL_NEUTRON_ONLY = '7.0'
# version of Fuel when classic provisioning is not available anymore.
FUEL_IMAGE_BASED_ONLY = '7.0'

View File

@ -1360,3 +1360,108 @@ class NetworkManager(object):
return []
return [consts.BOND_MODES.lacp_balance_tcp,
consts.BOND_MODES.l_802_3ad]
class AllocateVIPs70Mixin(object):
@classmethod
def find_network_role_by_id(cls, cluster, role_id):
"""Returns network role for specified role id.
:param cluster: Cluster instance
:param role_id: Network role id
:type role_id: str
:return: Network role dict or None if not found
"""
net_roles = objects.Cluster.get_network_roles(cluster)
for role in net_roles:
if role['id'] == role_id:
return role
return None
@classmethod
def get_end_point_ip(cls, cluster_id):
cluster_db = objects.Cluster.get_by_uid(cluster_id)
net_role = cls.find_network_role_by_id(cluster_db, 'public/vip')
if net_role:
node_group = objects.Cluster.get_controllers_node_group(cluster_db)
net_group_mapping = cls.build_role_to_network_group_mapping(
cluster_db, node_group.name)
net_group = cls.get_network_group_for_role(
net_role, net_group_mapping)
return cls.assign_vip(cluster_db, net_group, vip_type='public')
else:
raise errors.CanNotDetermineEndPointIP(
u'Can not determine end point IP for cluster %s' %
cluster_db.full_name)
@classmethod
def _assign_vips_for_net_groups(cls, cluster):
net_roles = objects.Cluster.get_network_roles(cluster)
node_group = objects.Cluster.get_controllers_node_group(cluster)
net_group_mapping = cls.build_role_to_network_group_mapping(
cluster, node_group.name)
for role in net_roles:
properties = role.get('properties', {})
net_group = cls.get_network_group_for_role(role, net_group_mapping)
for vip_info in properties.get('vip', ()):
vip_name = vip_info['name']
vip_addr = cls.assign_vip(
cluster, net_group, vip_type=vip_name)
yield role, vip_info, vip_addr
@classmethod
def assign_vips_for_net_groups_for_api(cls, cluster):
"""Calls cls.assign_vip for all vips in network roles.
Returns dict with vip definitions in API compatible format::
{
"vip_alias": "172.16.0.1"
}
:param cluster: Cluster instance
:type cluster: Cluster model
:return: dict with vip definitions
"""
vips = {}
for role, vip_info, vip_addr in cls._assign_vips_for_net_groups(
cluster):
alias = vip_info.get('alias')
if alias:
vips[alias] = vip_addr
return vips
@classmethod
def assign_vips_for_net_groups(cls, cluster):
"""Calls cls.assign_vip for all vips in network roles.
To be used for the output generation for orchestrator.
Returns dict with vip definitions like::
{
"vip_name": {
"network_role": "public",
"namespace": "haproxy",
"ipaddr": "172.16.0.1"
}
}
:param cluster: Cluster instance
:type cluster: Cluster model
:return: dict with vip definitions
"""
vips = {}
for role, vip_info, vip_addr in cls._assign_vips_for_net_groups(
cluster):
vip_name = vip_info['name']
vips[vip_name] = {
'network_role': role['id'],
'namespace': vip_info.get('namespace'),
'ipaddr': vip_addr,
'node_roles': vip_info.get('node_roles',
['controller',
'primary-controller'])
}
return vips

View File

@ -19,9 +19,8 @@ import six
from nailgun import consts
from nailgun.db import db
from nailgun.db.sqlalchemy.models import NeutronConfig
from nailgun.errors import errors
from nailgun import objects
from nailgun.network.manager import AllocateVIPs70Mixin
from nailgun.network.manager import NetworkManager
@ -66,10 +65,20 @@ class NeutronManager(NetworkManager):
return props
class NeutronManager70(NeutronManager):
class NeutronManager70(AllocateVIPs70Mixin, NeutronManager):
@classmethod
def build_role_to_network_group_mapping(cls, cluster, node_group_name):
"""Builds network role to network map according to template data if
template is loaded. Otherwise, empty map is returned.
:param cluster: Cluster instance
:type cluster: Cluster model
:param node_group_name: Node group name
:type node_group_name: string
:return: Network role to network map
:rtype: dict
"""
template = cluster.network_config.configuration_template
if template is None:
return {}
@ -104,105 +113,3 @@ class NeutronManager70(NeutronManager):
"""
return net_group_mapping.get(
network_role['id'], network_role['default_mapping'])
@classmethod
def find_network_role_by_id(cls, cluster, role_id):
"""Returns network role for specified role id.
:param cluster: Cluster instance
:param role_id: Network role id
:type role_id: str
:return: Network role dict or None if not found
"""
net_roles = objects.Cluster.get_network_roles(cluster)
for role in net_roles:
if role['id'] == role_id:
return role
return None
@classmethod
def get_end_point_ip(cls, cluster_id):
cluster_db = objects.Cluster.get_by_uid(cluster_id)
net_role = cls.find_network_role_by_id(cluster_db, 'public/vip')
if net_role:
node_group = objects.Cluster.get_controllers_node_group(cluster_db)
net_group_mapping = cls.build_role_to_network_group_mapping(
cluster_db, node_group.name)
net_group = cls.get_network_group_for_role(
net_role, net_group_mapping)
return cls.assign_vip(cluster_db, net_group, vip_type='public')
else:
raise errors.CanNotDetermineEndPointIP(
u'Can not determine end point IP for cluster %s' %
cluster_db.full_name)
@classmethod
def _assign_vips_for_net_groups(cls, cluster):
net_roles = objects.Cluster.get_network_roles(cluster)
node_group = objects.Cluster.get_controllers_node_group(cluster)
net_group_mapping = cls.build_role_to_network_group_mapping(
cluster, node_group.name)
for role in net_roles:
properties = role.get('properties', {})
net_group = cls.get_network_group_for_role(role, net_group_mapping)
for vip_info in properties.get('vip', ()):
vip_name = vip_info['name']
vip_addr = cls.assign_vip(
cluster, net_group, vip_type=vip_name)
yield role, vip_info, vip_addr
@classmethod
def assign_vips_for_net_groups_for_api(cls, cluster):
"""Calls cls.assign_vip for all vips in network roles.
Returns dict with vip definitions in API compatible format::
{
"vip_alias": "172.16.0.1"
}
:param cluster: Cluster instance
:type cluster: Cluster model
:return: dict with vip definitions
"""
vips = {}
for role, vip_info, vip_addr in cls._assign_vips_for_net_groups(
cluster):
alias = vip_info.get('alias')
if alias:
vips[alias] = vip_addr
return vips
@classmethod
def assign_vips_for_net_groups(cls, cluster):
"""Calls cls.assign_vip for all vips in network roles.
To be used for the output generation for orchestrator.
Returns dict with vip definitions like::
{
"vip_name": {
"network_role": "public",
"namespace": "haproxy",
"ipaddr": "172.16.0.1"
}
}
:param cluster: Cluster instance
:type cluster: Cluster model
:return: dict with vip definitions
"""
vips = {}
for role, vip_info, vip_addr in cls._assign_vips_for_net_groups(
cluster):
vip_name = vip_info['name']
vips[vip_name] = {
'network_role': role['id'],
'namespace': vip_info.get('namespace'),
'ipaddr': vip_addr,
'node_roles': vip_info.get('node_roles',
['controller',
'primary-controller'])
}
return vips

View File

@ -16,6 +16,8 @@
from nailgun.db import db
from nailgun.db.sqlalchemy.models import NovaNetworkConfig
from nailgun.network.manager import AllocateVIPs70Mixin
from nailgun.network.manager import NetworkManager
@ -44,3 +46,29 @@ class NovaNetworkManager(NetworkManager):
if ng.get("vlan_start") is None:
return []
return [int(ng.get("vlan_start"))]
class NovaNetworkManager70(AllocateVIPs70Mixin, NovaNetworkManager):
@classmethod
def build_role_to_network_group_mapping(cls, *_):
"""Default network role to network mapping is used always so
map building is not required.
:return: Empty network role to network map
:rtype: dict
"""
return {}
@classmethod
def get_network_group_for_role(cls, network_role, _):
"""Returns network group to which network role is associated.
The default network group from the network role description is
returned.
:param network_role: Network role dict
:type network_role: dict
:return: Network group name
:rtype: str
"""
return network_role['default_mapping']

View File

@ -366,14 +366,17 @@ class Cluster(NailgunObject):
from nailgun.network.manager import NetworkManager
return NetworkManager
ver = instance.release.environment_version
if instance.net_provider == 'neutron':
ver = instance.release.environment_version
if StrictVersion(ver) >= StrictVersion(consts.FUEL_NEUTRON_ONLY):
if StrictVersion(ver) >= StrictVersion('7.0'):
from nailgun.network.neutron import NeutronManager70
return NeutronManager70
from nailgun.network.neutron import NeutronManager
return NeutronManager
else:
if StrictVersion(ver) >= StrictVersion('7.0'):
from nailgun.network.nova_network import NovaNetworkManager70
return NovaNetworkManager70
from nailgun.network.nova_network import NovaNetworkManager
return NovaNetworkManager

View File

@ -125,7 +125,7 @@ class TestHandlers(BaseIntegrationTest):
def test_if_cluster_creates_correct_networks(self):
release = Release()
release.version = "1.1.1"
release.version = "1111-6.0"
release.name = u"release_name_" + str(release.version)
release.description = u"release_desc" + str(release.version)
release.operating_system = "CentOS"

View File

@ -25,6 +25,7 @@ from netaddr import IPRange
from sqlalchemy import not_
import nailgun
from nailgun import consts
from nailgun.errors import errors
from nailgun import objects
@ -36,6 +37,7 @@ from nailgun.db.sqlalchemy.models import NodeNICInterface
from nailgun.network.neutron import NeutronManager
from nailgun.network.neutron import NeutronManager70
from nailgun.network.nova_network import NovaNetworkManager
from nailgun.network.nova_network import NovaNetworkManager70
from nailgun.test.base import BaseIntegrationTest
from nailgun.test.base import fake_tasks
@ -603,14 +605,13 @@ class TestNeutronManager70(BaseNetworkManagerTest):
super(TestNeutronManager70, self).setUp()
self.cluster = self._create_env()
self.net_manager = objects.Cluster.get_network_manager(self.cluster)
self.assertIs(self.net_manager, NeutronManager70)
def _create_env(self):
return self.env.create(
release_kwargs={'version': '1111-7.0'},
cluster_kwargs={
'api': False,
'net_provider': 'neutron'
'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron
}
)
@ -629,6 +630,9 @@ class TestNeutronManager70(BaseNetworkManagerTest):
network_role.update(kwargs)
return network_role
def test_get_network_manager(self):
self.assertIs(self.net_manager, NeutronManager70)
def test_get_network_group_for_role(self):
net_template = self.env.read_fixtures(['network_template'])[0]
objects.Cluster.set_network_template(self.cluster, net_template)
@ -740,3 +744,46 @@ class TestNeutronManager70(BaseNetworkManagerTest):
self.cluster, vips_to_assign)
vips = self.net_manager.get_assigned_vips(self.cluster)
self.assertEqual(vips_to_assign, vips)
class TestNovaNetworkManager70(TestNeutronManager70):
def _create_env(self):
return self.env.create(
release_kwargs={'version': '1111-7.0'},
cluster_kwargs={
'api': False,
'net_provider': consts.CLUSTER_NET_PROVIDERS.nova_network
}
)
def test_get_network_manager(self):
self.assertIs(self.net_manager, NovaNetworkManager70)
def test_get_network_group_for_role(self):
node_group = objects.Cluster.get_controllers_node_group(self.cluster)
net_group_mapping = \
self.net_manager.build_role_to_network_group_mapping(
self.cluster, node_group.name)
self.assertEqual(
self.net_manager.get_network_group_for_role(
self._get_network_role_metadata(id='public/vip'),
net_group_mapping),
'public')
self.assertEqual(
self.net_manager.get_network_group_for_role(
self._get_network_role_metadata(
id='role_not_in_template',
default_mapping='default_net_group'), net_group_mapping),
'default_net_group')
def test_get_endpoint_ip(self):
vip = '172.16.0.1'
with patch.object(NovaNetworkManager70, 'assign_vip',
return_value=vip) as assign_vip_mock:
endpoint_ip = self.net_manager.get_end_point_ip(self.cluster.id)
assign_vip_mock.assert_called_once_with(
self.cluster, mock.ANY, vip_type='public')
self.assertEqual(endpoint_ip, vip)

View File

@ -59,7 +59,6 @@ class BaseTestDeploymentAttributesSerialization70(BaseDeploymentSerializer):
super(BaseTestDeploymentAttributesSerialization70, self).setUp()
self.cluster = self.create_env('ha_compact')
# NOTE: 'prepare_for_deployment' is going to be changed for 7.0
objects.NodeCollection.prepare_for_deployment(
self.env.nodes, self.segmentation_type)
self.cluster_db = self.db.query(models.Cluster).get(self.cluster['id'])
@ -82,6 +81,16 @@ class BaseTestDeploymentAttributesSerialization70(BaseDeploymentSerializer):
{'roles': ['compute'],
'pending_addition': True}])
def check_vips_serialized(self, vips_data):
vips_names = ['vrouter', 'management', 'vrouter_pub', 'public']
self.assertItemsEqual(vips_data,
vips_names)
for vip in vips_names:
self.assertItemsEqual(
vips_data[vip],
['network_role', 'namespace', 'ipaddr', 'node_roles']
)
class TestDeploymentAttributesSerialization70(
BaseTestDeploymentAttributesSerialization70
@ -183,6 +192,7 @@ class TestDeploymentAttributesSerialization70(
[ip_by_net['private']] * len(self.private))
self.assertEqual(v['network_roles'], dict(network_roles))
self.check_vips_serialized(node_data['network_metadata']['vips'])
def test_generate_vmware_attributes_data(self):
self.check_generate_vmware_attributes_data()
@ -210,24 +220,13 @@ class TestDeploymentAttributesSerializationSegmentationTun70(
segmentation_type = consts.NEUTRON_SEGMENT_TYPES.tun
class TestDeploymentSerializationForNovaNetwork70(BaseDeploymentSerializer):
@mock.patch.object(models.Release, 'environment_version',
new_callable=mock.PropertyMock(return_value='7.0'))
def setUp(self, *args):
super(TestDeploymentSerializationForNovaNetwork70, self).setUp()
self.cluster = self.create_env('ha_compact')
# NOTE: 'prepare_for_deployment' is going to be changed for 7.0
objects.NodeCollection.prepare_for_deployment(self.env.nodes)
cluster_db = self.db.query(models.Cluster).get(self.cluster['id'])
serializer_type = get_serializer_for_cluster(cluster_db)
self.serializer = serializer_type(AstuteGraph(cluster_db))
self.serialized_for_astute = self.serializer.serialize(
cluster_db, cluster_db.nodes)
self.vm_data = self.env.read_fixtures(['vmware_attributes'])
class TestDeploymentSerializationForNovaNetwork70(
BaseTestDeploymentAttributesSerialization70
):
def create_env(self, mode):
return self.env.create(
release_kwargs={'version': '2015.1.0-7.0'},
cluster_kwargs={
'mode': mode,
'net_provider': consts.CLUSTER_NET_PROVIDERS.nova_network},
@ -355,6 +354,7 @@ class TestDeploymentSerializationForNovaNetwork70(BaseDeploymentSerializer):
node_attrs['network_roles'],
network_roles
)
self.check_vips_serialized(node_data['network_metadata']['vips'])
def test_generate_vmware_attributes_data(self):
self.check_generate_vmware_attributes_data()