Add initial support of multi-rack for upgrades

* netgroups mapping was changed (additional argument
  for the mapping was added - name of node group)
* copying of node group during cluster cloning was added

Depends-On: I2638279371e91f15090c782fc5fdbb434a2e85f8
Partial-bug: #1612297

Change-Id: Ib1689d7b6d673c0d78434dd047a7ebc520c232e7
Co-Authored-By: Ryan Moe <rmoe@mirantis.com>
Co-Authored-By: Andrew Woodward <awoodward@mirantis.com>
Co-Authored-By: Ilya Kharin <akscram@gmail.com>
This commit is contained in:
Anastasiya 2016-08-29 16:46:20 +03:00 committed by Anastasia Balobashina
parent 4136bc9aed
commit e2b9dbf1ca
7 changed files with 87 additions and 38 deletions

View File

@ -140,11 +140,8 @@ class CopyVIPsHandler(base.BaseHandler):
self.checked_data(cluster=cluster, relation=relation)
# get original cluster object and create adapter with it
orig_cluster_adapter = \
adapters.NailgunClusterAdapter(
adapters.NailgunClusterAdapter.get_by_uid(
relation.orig_cluster_id)
)
orig_cluster_adapter = adapters.NailgunClusterAdapter.get_by_uid(
relation.orig_cluster_id)
seed_cluster_adapter = adapters.NailgunClusterAdapter(cluster)

View File

@ -35,6 +35,10 @@ class NailgunClusterAdapter(object):
def name(self):
return self.cluster.name
@property
def node_groups(self):
return self.cluster.node_groups
@property
def net_provider(self):
return self.cluster.net_provider
@ -135,8 +139,9 @@ class NailgunNetworkManager(object):
def update(self, network_configuration):
self.net_manager.update(self.cluster, network_configuration)
def get_assigned_vips(self):
return self.net_manager.get_assigned_vips(self.cluster)
def get_assigned_vips(self, network_names=None):
return self.net_manager.get_assigned_vips(
self.cluster, network_names=network_names)
def assign_vips_for_net_groups(self):
return self.net_manager.assign_vips_for_net_groups(self.cluster)
@ -230,3 +235,11 @@ class NailgunNetworkGroupAdapter(object):
@property
def name(self):
return self.network_group.name
@property
def nodegroup(self):
return self.network_group.nodegroup
@classmethod
def get_by_uid(cls, ng_id):
return objects.NetworkGroup.get_by_uid(ng_id)

View File

@ -13,7 +13,6 @@
# 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 unittest
import mock
@ -227,7 +226,7 @@ class TestNodeReassignHandler(base.BaseIntegrationTest):
class TestCopyVipsHandler(tests_base.BaseCloneClusterTest):
@unittest.skip("Skip test regarding vips")
def test_copy_vips(self):
node_db = self.env.create_node(cluster_id=self.src_cluster.id,
roles=["controller"])

View File

@ -10,7 +10,6 @@
# License for the specific language governing permissions and limitations
# under the License.
from distutils import version
import unittest
import mock
from nailgun.test import base as nailgun_test_base
@ -249,33 +248,32 @@ class TestClusterTransformers(nailgun_test_base.BaseUnitTest):
class TestVipTransformers(nailgun_test_base.BaseUnitTest):
def setUp(self):
ip = '0.0.0.0'
self.data = {
'management': {
1: {
'haproxy': ip,
'vrouter': ip,
'test': ip,
},
'public': {
2: {
'haproxy': ip,
'vrouter': ip,
'test': ip,
}
}
self.mapping = {1: 'management', 2: 'public'}
@unittest.skip("Skip test regarding vips")
def test_vip_transform(self):
ip = '0.0.0.0'
data = vip.transform_vips(self.data)
data = vip.transform_vips((self.data, self.mapping))
self.assertEqual(
data, {
'management': {
data, ({
1: {
'management': ip,
'vrouter': ip,
},
'public': {
2: {
'public': ip,
'vrouter_pub': ip,
}}
}}, {1: 'management', 2: 'public'})
)

View File

@ -15,7 +15,6 @@
# under the License.
import copy
import unittest
import six
@ -146,7 +145,6 @@ class TestUpgradeHelperCloneCluster(base_tests.BaseCloneClusterTest):
self.assertEqual(public_net['ip_ranges'],
self.public_net_data['ip_ranges'])
@unittest.skip("Skip test regarding vips")
def test_copy_vips(self):
# save network information before node reassignment to seed cluster
# as after that no VIP will be allocated/serialized due to

View File

@ -42,17 +42,17 @@ def transform_vips(data):
},
}
renamed_vips = collections.defaultdict(dict)
for ng_name, vips_obj in data.items():
ng_vip_rules = rename_vip_rules[ng_name]
vips, id_name_mapping = data
for ng_id, vips_obj in vips.items():
ng_vip_rules = rename_vip_rules[id_name_mapping[ng_id]]
for vip_name, vip_addr in vips_obj.items():
if vip_name not in ng_vip_rules:
continue
new_vip_name = ng_vip_rules[vip_name]
renamed_vips[ng_name][new_vip_name] = vip_addr
renamed_vips[ng_id][new_vip_name] = vip_addr
return renamed_vips
return renamed_vips, id_name_mapping
class Manager(transformations.Manager):

View File

@ -15,6 +15,8 @@
# under the License.
import copy
import collections
import six
from nailgun import consts
@ -47,13 +49,22 @@ def merge_attributes(a, b):
return attrs
def get_net_key(net):
group_name = None
if net["group_id"]:
group_name = objects.NodeGroup.get_by_uid(net["group_id"]).name
return (net["name"], group_name)
def merge_nets(a, b):
new_settings = copy.deepcopy(b)
source_networks = dict((n["name"], n) for n in a["networks"])
source_networks = dict((get_net_key(net), net) for net in a["networks"])
for net in new_settings["networks"]:
if net["name"] not in source_networks:
net_key = get_net_key(net)
if net_key not in source_networks:
continue
source_net = source_networks[net["name"]]
source_net = source_networks[net_key]
for key, value in six.iteritems(net):
if (key not in ("cluster_id", "id", "meta", "group_id") and
key in source_net):
@ -84,6 +95,7 @@ class UpgradeHelper(object):
new_cluster = cls.create_cluster_clone(orig_cluster, data)
cls.copy_attributes(orig_cluster, new_cluster)
cls.copy_node_groups(orig_cluster, new_cluster)
cls.copy_network_config(orig_cluster, new_cluster)
relations.UpgradeRelationObject.create_relation(orig_cluster.id,
new_cluster.id)
@ -124,6 +136,18 @@ class UpgradeHelper(object):
attrs = new_cluster.attributes
attrs['editable']['provision']['method']['value'] = 'image'
@classmethod
def copy_node_groups(cls, orig_cluster, new_cluster):
for ng in orig_cluster.node_groups:
if getattr(ng, 'is_default', False) or ng.name == 'default':
continue
data = {
'name': ng.name,
'cluster_id': new_cluster.id
}
objects.NodeGroup.create(data)
@classmethod
def copy_network_config(cls, orig_cluster, new_cluster):
nets_serializer = cls.network_serializers[orig_cluster.net_provider]
@ -140,19 +164,37 @@ class UpgradeHelper(object):
orig_net_manager = orig_cluster.get_network_manager()
new_net_manager = new_cluster.get_network_manager()
vips = {}
assigned_vips = orig_net_manager.get_assigned_vips()
for ng_name in (consts.NETWORKS.public, consts.NETWORKS.management):
vips[ng_name] = assigned_vips[ng_name]
vips = orig_net_manager.get_assigned_vips(
network_names=(consts.NETWORKS.public, consts.NETWORKS.management))
vips = cls.vip_transformations.apply(
netgroups_id_mapping = cls.get_netgroups_id_mapping(orig_cluster,
new_cluster)
new_vips = cls.reassociate_vips(vips, netgroups_id_mapping)
id_name_vips_mapping = cls.get_id_name_vips_mapping(new_vips)
new_vips, id_name_vips_mapping = cls.vip_transformations.apply(
orig_cluster.release.environment_version,
new_cluster.release.environment_version,
vips
(new_vips, id_name_vips_mapping),
)
new_net_manager.assign_given_vips_for_net_groups(vips)
new_net_manager.assign_given_vips_for_net_groups(new_vips)
new_net_manager.assign_vips_for_net_groups()
@classmethod
def reassociate_vips(cls, vips, netgroups_id_mapping):
new_vips = collections.defaultdict(dict)
for orig_net_id, net_vips in vips.items():
new_net_id = netgroups_id_mapping[orig_net_id]
new_vips[new_net_id] = net_vips
return new_vips
@classmethod
def get_id_name_vips_mapping(self, vips):
mapping = {}
for vip_id in vips:
mapping[vip_id] = \
adapters.NailgunNetworkGroupAdapter.get_by_uid(vip_id).name
return mapping
@classmethod
def get_node_roles(cls, reprovision, current_roles, given_roles):
"""Return roles depending on the reprovisioning status.
@ -210,8 +252,10 @@ class UpgradeHelper(object):
orig_ng = orig_cluster.get_network_groups()
seed_ng = seed_cluster.get_network_groups()
seed_ng_dict = dict((ng.name, ng.id) for ng in seed_ng)
mapping = dict((ng.id, seed_ng_dict[ng.name]) for ng in orig_ng)
seed_ng_dict = dict(((ng.name, ng.nodegroup.name), ng.id)
for ng in seed_ng)
mapping = dict((ng.id, seed_ng_dict[(ng.name, ng.nodegroup.name)])
for ng in orig_ng)
mapping[orig_cluster.get_admin_network_group().id] = \
seed_cluster.get_admin_network_group().id
return mapping