1952 lines
77 KiB
Python
1952 lines
77 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
# Copyright 2015 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 collections
|
|
import copy
|
|
import mock
|
|
import netaddr
|
|
import six
|
|
import yaml
|
|
|
|
from oslo_serialization import jsonutils
|
|
|
|
from nailgun import consts
|
|
from nailgun.db import db
|
|
from nailgun.db.sqlalchemy import models
|
|
from nailgun import objects
|
|
from nailgun.orchestrator import stages
|
|
from nailgun.test import base
|
|
from nailgun.test.base import DeploymentTasksTestMixin
|
|
from nailgun.utils import reverse
|
|
|
|
from nailgun.orchestrator.deployment_serializers import \
|
|
deployment_info_to_legacy
|
|
from nailgun.orchestrator.deployment_serializers import \
|
|
get_serializer_for_cluster
|
|
from nailgun.orchestrator.orchestrator_graph import AstuteGraph
|
|
from nailgun.test.integration.test_orchestrator_serializer import \
|
|
BaseDeploymentSerializer
|
|
from nailgun.test.integration.test_orchestrator_serializer import \
|
|
TestDeploymentHASerializer61
|
|
from nailgun.test.integration.test_orchestrator_serializer import \
|
|
TestNovaOrchestratorSerializer
|
|
from nailgun.test.integration.test_orchestrator_serializer import \
|
|
TestSerializeInterfaceDriversData
|
|
|
|
from nailgun.extensions.network_manager.serializers.neutron_serializers \
|
|
import NeutronNetworkDeploymentSerializer70
|
|
from nailgun.extensions.network_manager.serializers.neutron_serializers \
|
|
import NeutronNetworkTemplateSerializer70
|
|
|
|
|
|
class PrepareDataMixin(object):
|
|
|
|
def patch_net_roles_for_release(self):
|
|
rel_id = self.env.create_release(version=self.env_version).id
|
|
rel_db = self.db.query(models.Release).filter_by(id=rel_id).one()
|
|
|
|
to_patch = yaml.safe_load("""
|
|
-
|
|
id: "keystone/api"
|
|
default_mapping: "management"
|
|
properties: &default_network_roles_metadata_properties
|
|
subnet: true
|
|
gateway: false
|
|
vip: []
|
|
-
|
|
id: "admin/pxe"
|
|
default_mapping: "fuelweb_admin"
|
|
properties:
|
|
subnet: true
|
|
gateway: true
|
|
vip: []
|
|
-
|
|
id: "swift/api"
|
|
default_mapping: "management"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "neutron/api"
|
|
default_mapping: "management"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "sahara/api"
|
|
default_mapping: "management"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "ceilometer/api"
|
|
default_mapping: "management"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "cinder/api"
|
|
default_mapping: "management"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "glance/api"
|
|
default_mapping: "management"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "heat/api"
|
|
default_mapping: "management"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "nova/api"
|
|
default_mapping: "management"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "murano/api"
|
|
default_mapping: "management"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "horizon"
|
|
default_mapping: "management"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "mgmt/memcache"
|
|
default_mapping: "management"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "mgmt/database"
|
|
default_mapping: "management"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "mgmt/messaging"
|
|
default_mapping: "management"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "mgmt/corosync"
|
|
default_mapping: "management"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "mgmt/vip"
|
|
default_mapping: "management"
|
|
properties:
|
|
subnet: true
|
|
gateway: false
|
|
vip:
|
|
-
|
|
name: "vrouter"
|
|
namespace: "vrouter"
|
|
alias: "management_vrouter_vip"
|
|
-
|
|
name: "management"
|
|
namespace: "haproxy"
|
|
alias: "management_vip"
|
|
-
|
|
id: "public/vip"
|
|
default_mapping: "public"
|
|
properties:
|
|
subnet: true
|
|
gateway: true
|
|
vip:
|
|
-
|
|
name: "vrouter_pub"
|
|
namespace: "vrouter"
|
|
alias: "public_vrouter_vip"
|
|
-
|
|
name: "public"
|
|
namespace: "haproxy"
|
|
alias: "public_vip"
|
|
-
|
|
id: "neutron/private"
|
|
default_mapping: "private"
|
|
properties:
|
|
subnet: false
|
|
gateway: false
|
|
vip: []
|
|
-
|
|
id: "neutron/mesh"
|
|
default_mapping: "private"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "neutron/floating"
|
|
default_mapping: "public"
|
|
properties:
|
|
subnet: false
|
|
gateway: false
|
|
vip: []
|
|
-
|
|
id: "swift/replication"
|
|
default_mapping: "storage"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "ceph/public"
|
|
default_mapping: "management"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "ceph/radosgw"
|
|
default_mapping: "public"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "ceph/replication"
|
|
default_mapping: "storage"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "cinder/iscsi"
|
|
default_mapping: "storage"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "mongo/db"
|
|
default_mapping: "management"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "fw-admin"
|
|
default_mapping: "fuelweb_admin"
|
|
properties:
|
|
subnet: true
|
|
gateway: true
|
|
vip: []
|
|
-
|
|
id: "management"
|
|
default_mapping: "management"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "ex"
|
|
default_mapping: "public"
|
|
properties:
|
|
subnet: true
|
|
gateway: true
|
|
vip: []
|
|
-
|
|
id: "storage"
|
|
default_mapping: "storage"
|
|
properties: *default_network_roles_metadata_properties
|
|
-
|
|
id: "nova/migration"
|
|
default_mapping: "management"
|
|
properties: *default_network_roles_metadata_properties
|
|
""")
|
|
rel_db.network_roles_metadata = to_patch
|
|
self.db.flush()
|
|
return rel_db
|
|
|
|
|
|
class BaseTestDeploymentAttributesSerialization70(BaseDeploymentSerializer,
|
|
PrepareDataMixin):
|
|
management = ['keystone/api', 'neutron/api', 'swift/api', 'sahara/api',
|
|
'ceilometer/api', 'cinder/api', 'glance/api', 'heat/api',
|
|
'nova/api', 'murano/api', 'horizon', 'management',
|
|
'mgmt/database', 'mgmt/messaging', 'mgmt/corosync',
|
|
'mgmt/memcache', 'mgmt/vip', 'mongo/db',
|
|
'ceph/public', 'nova/migration']
|
|
fuelweb_admin = ['admin/pxe', 'fw-admin']
|
|
neutron = ['neutron/private', 'neutron/floating']
|
|
storage = ['storage', 'ceph/replication', 'swift/replication',
|
|
'cinder/iscsi']
|
|
public = ['ex', 'public/vip', 'ceph/radosgw']
|
|
private = ['neutron/mesh']
|
|
|
|
networks = ['fuelweb_admin', 'storage', 'management', 'public', 'private']
|
|
|
|
# Must be set in subclasses
|
|
segmentation_type = None
|
|
env_version = '2015.1.0-7.0'
|
|
|
|
def setUp(self):
|
|
super(BaseTestDeploymentAttributesSerialization70, self).setUp()
|
|
self.cluster = self.create_env(consts.CLUSTER_MODES.ha_compact)
|
|
|
|
objects.Cluster.prepare_for_deployment(self.env.clusters[-1])
|
|
self.cluster_db = self.db.query(models.Cluster).get(self.cluster['id'])
|
|
serializer_type = get_serializer_for_cluster(self.cluster_db)
|
|
self.serializer = serializer_type(AstuteGraph(self.cluster_db))
|
|
self.serialized_for_astute = self.serializer.serialize(
|
|
self.cluster_db, self.cluster_db.nodes)
|
|
self.serialized_for_astute = deployment_info_to_legacy(
|
|
self.serialized_for_astute)
|
|
self.vm_data = self.env.read_fixtures(['vmware_attributes'])
|
|
|
|
def create_env(self, mode):
|
|
release = self.patch_net_roles_for_release()
|
|
|
|
return self.env.create(
|
|
cluster_kwargs={
|
|
'release_id': release.id,
|
|
'mode': mode,
|
|
'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
|
|
'net_segment_type': self.segmentation_type},
|
|
nodes_kwargs=[
|
|
{'roles': ['controller'],
|
|
'pending_addition': True},
|
|
{'roles': ['compute'],
|
|
'pending_addition': True}])
|
|
|
|
def check_vips_serialized(self, node_data):
|
|
vips_names = ['vrouter', 'management', 'vrouter_pub', 'public']
|
|
# check that vip-related info is not in root
|
|
self.assertTrue(all(vip_name not in node_data
|
|
for vip_name in vips_names))
|
|
vips_data = node_data['network_metadata']['vips']
|
|
self.assertItemsEqual(vips_data,
|
|
vips_names)
|
|
for vip in vips_names:
|
|
self.assertItemsEqual(
|
|
vips_data[vip],
|
|
['network_role', 'namespace',
|
|
'ipaddr', 'node_roles', 'is_user_defined']
|
|
)
|
|
|
|
|
|
class TestDeploymentAttributesSerialization70(
|
|
BaseTestDeploymentAttributesSerialization70
|
|
):
|
|
segmentation_type = consts.NEUTRON_SEGMENT_TYPES.vlan
|
|
custom_network = {
|
|
'name': 'custom',
|
|
'role': 'plugin/custom',
|
|
'cidr': '192.168.3.0/24',
|
|
'vlan_start': 50,
|
|
'bridge': 'br-custom',
|
|
}
|
|
plugin_network_roles = yaml.safe_load("""
|
|
- id: "{role}"
|
|
default_mapping: "{name}"
|
|
properties:
|
|
subnet: true
|
|
gateway: false
|
|
vip:
|
|
- name: "{name}"
|
|
namespace: "haproxy"
|
|
""".format(**custom_network))
|
|
|
|
def test_non_default_bridge_mapping(self):
|
|
expected_mapping = {
|
|
u'test': u'br-test',
|
|
u'testnetwork1': u'br-testnetwork',
|
|
u'testnetwork13': u'br-testnetwork',
|
|
u'my-super-network': u'br-my-super-net',
|
|
u'uplink-network-east': u'br-uplink-netw',
|
|
u'uplink-network-west': u'br-uplink-netw',
|
|
u'uplink-network-south': u'br-uplink-netw',
|
|
u'12345uplink-network-south': u'br-12345uplink',
|
|
u'fw-admin': u'br-fw-admi'
|
|
}
|
|
cluster = self.env.create(
|
|
cluster_kwargs={
|
|
'release_id': self.env.releases[0].id,
|
|
'mode': consts.CLUSTER_MODES.ha_compact,
|
|
'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
|
|
'net_segment_type': self.segmentation_type})
|
|
self.cluster_db = objects.Cluster.get_by_uid(cluster['id'])
|
|
for name in expected_mapping:
|
|
self.env._create_network_group(cluster=self.cluster_db,
|
|
name=name)
|
|
self.env.create_node(
|
|
api=True,
|
|
cluster_id=cluster['id'],
|
|
pending_roles=['controller'],
|
|
pending_addition=True)
|
|
net_serializer = self.serializer.get_net_provider_serializer(
|
|
self.cluster_db)
|
|
objects.Cluster.prepare_for_deployment(self.cluster_db)
|
|
mapping = net_serializer.get_node_non_default_bridge_mapping(
|
|
self.cluster_db.nodes[0])
|
|
|
|
# since we have a suffix generation for bridges, they may have
|
|
# different suffix based on PYTHONHASHSEED. hence, we can't
|
|
# come up with a normal dictionary comparison. so let's
|
|
# compare that all bridges are unique, and they are unique
|
|
# for networks which may have bridge collision.
|
|
br_collision = collections.defaultdict(list)
|
|
self.assertEqual(len(mapping), len(expected_mapping))
|
|
self.assertEqual(len(expected_mapping), len(set(mapping.values())))
|
|
|
|
for netname in expected_mapping:
|
|
# check that bridge name has been generated from the network
|
|
self.assertTrue(
|
|
mapping[netname].startswith(expected_mapping[netname]))
|
|
|
|
br_collision[expected_mapping[netname]].append(netname)
|
|
|
|
# check that there's no collision between networks
|
|
for bridge, netnames in six.iteritems(br_collision):
|
|
bridges = set((mapping[netname] for netname in netnames))
|
|
self.assertEqual(len(bridges), len(netnames))
|
|
|
|
def test_network_scheme_custom_networks(self):
|
|
cluster = self.env.create(
|
|
cluster_kwargs={
|
|
'release_id': self.env.releases[0].id,
|
|
'mode': consts.CLUSTER_MODES.ha_compact,
|
|
'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
|
|
'net_segment_type': self.segmentation_type})
|
|
self.cluster_db = objects.Cluster.get_by_uid(cluster['id'])
|
|
self.env._create_network_group(cluster=self.cluster_db,
|
|
name=self.custom_network['name'],
|
|
cidr=self.custom_network['cidr'],
|
|
vlan_start=self.custom_network[
|
|
'vlan_start'
|
|
])
|
|
self.env.create_plugin(
|
|
cluster=self.cluster_db,
|
|
network_roles_metadata=self.plugin_network_roles,
|
|
package_version='3.0.0')
|
|
|
|
self.env.create_node(
|
|
api=True,
|
|
cluster_id=cluster['id'],
|
|
pending_roles=['controller'],
|
|
pending_addition=True)
|
|
objects.Cluster.prepare_for_deployment(self.cluster_db)
|
|
serializer = self.create_serializer(self.cluster_db)
|
|
serialized_for_astute = serializer.serialize(
|
|
self.cluster_db, self.cluster_db.nodes
|
|
)
|
|
serialized_for_astute = deployment_info_to_legacy(
|
|
serialized_for_astute)
|
|
for node in serialized_for_astute:
|
|
vips = node['network_metadata']['vips']
|
|
roles = node['network_scheme']['roles']
|
|
transformations = node['network_scheme']['transformations']
|
|
node_network_roles = (node['network_metadata']['nodes']
|
|
['node-' + node['uid']]['network_roles'])
|
|
custom_ip = node_network_roles.get(self.custom_network['role'],
|
|
'0.0.0.0')
|
|
custom_brs = filter(lambda t: t.get('name') ==
|
|
self.custom_network['bridge'],
|
|
transformations)
|
|
custom_ports = filter(lambda t: t.get('name') ==
|
|
("eth0.%s" %
|
|
self.custom_network['vlan_start']),
|
|
transformations)
|
|
self.assertEqual(roles.get(self.custom_network['role']),
|
|
self.custom_network['bridge'])
|
|
self.assertEqual(vips.get(self.custom_network['name'],
|
|
{}).get('network_role'),
|
|
self.custom_network['role'])
|
|
self.assertTrue(netaddr.IPAddress(custom_ip) in
|
|
netaddr.IPNetwork(self.custom_network['cidr']))
|
|
self.assertEqual(len(custom_brs), 1)
|
|
self.assertEqual(len(custom_ports), 1)
|
|
self.assertEqual(custom_ports[0]['bridge'],
|
|
self.custom_network['bridge'])
|
|
|
|
def test_network_scheme(self):
|
|
for node in self.serialized_for_astute:
|
|
roles = node['network_scheme']['roles']
|
|
node = objects.Node.get_by_uid(node['uid'])
|
|
|
|
expected_roles = zip(
|
|
self.management, ['br-mgmt'] * len(self.management))
|
|
expected_roles += zip(
|
|
self.fuelweb_admin, ['br-fw-admin'] * len(self.fuelweb_admin))
|
|
expected_roles += zip(
|
|
self.storage, ['br-storage'] * len(self.storage))
|
|
|
|
if objects.Node.should_have_public(node):
|
|
expected_roles += zip(
|
|
self.public, ['br-ex'] * len(self.public))
|
|
expected_roles += [('neutron/floating', 'br-floating')]
|
|
|
|
if node.cluster.network_config.segmentation_type == \
|
|
consts.NEUTRON_SEGMENT_TYPES.vlan:
|
|
expected_roles += [('neutron/private', 'br-prv')]
|
|
|
|
if node.cluster.network_config.segmentation_type in \
|
|
(consts.NEUTRON_SEGMENT_TYPES.gre,
|
|
consts.NEUTRON_SEGMENT_TYPES.tun):
|
|
expected_roles += [('neutron/mesh', 'br-mesh')]
|
|
|
|
self.assertEqual(roles, dict(expected_roles))
|
|
|
|
def test_network_metadata(self):
|
|
neutron_serializer = self.serializer.get_net_provider_serializer(
|
|
self.cluster_db)
|
|
for node_data in self.serialized_for_astute:
|
|
self.assertItemsEqual(
|
|
node_data['network_metadata'], ['nodes', 'vips'])
|
|
for k, v in six.iteritems(node_data['network_metadata']['nodes']):
|
|
self.assertItemsEqual(
|
|
v,
|
|
['uid', 'fqdn', 'name', 'user_node_name',
|
|
'swift_zone', 'node_roles', 'network_roles']
|
|
)
|
|
node = objects.Node.get_by_uid(v['uid'])
|
|
ip_by_net = neutron_serializer.get_network_to_ip_mapping(node)
|
|
|
|
self.assertEqual(objects.Node.get_slave_name(node), k)
|
|
self.assertEqual(v['uid'], node.uid)
|
|
self.assertEqual(v['fqdn'], objects.Node.get_node_fqdn(node))
|
|
self.assertEqual(v['name'], k)
|
|
self.assertEqual(v['user_node_name'], node.name)
|
|
self.assertEqual(v['swift_zone'], node.uid)
|
|
|
|
network_roles = zip(self.management,
|
|
[ip_by_net['management']] * len(
|
|
self.management))
|
|
network_roles += zip(self.fuelweb_admin,
|
|
[ip_by_net['fuelweb_admin']] * len(
|
|
self.fuelweb_admin))
|
|
network_roles += zip(
|
|
self.storage, [ip_by_net['storage']] * len(self.storage))
|
|
network_roles += zip(self.neutron, [None] * len(self.neutron))
|
|
|
|
if objects.Node.should_have_public(node):
|
|
network_roles += zip(
|
|
self.public, [ip_by_net['public']] * len(self.public))
|
|
|
|
if node.cluster.network_config.segmentation_type in \
|
|
(consts.NEUTRON_SEGMENT_TYPES.gre,
|
|
consts.NEUTRON_SEGMENT_TYPES.tun):
|
|
network_roles += zip(
|
|
self.private,
|
|
[ip_by_net['private']] * len(self.private))
|
|
|
|
self.assertEqual(v['network_roles'], dict(network_roles))
|
|
self.check_vips_serialized(node_data)
|
|
|
|
def test_generate_vmware_attributes_data(self):
|
|
self.check_generate_vmware_attributes_data()
|
|
|
|
result = self.serializer.serialize_node(
|
|
self.env.nodes[0], 'compute-vmware'
|
|
)
|
|
|
|
self.assertEqual(
|
|
result['vcenter']['computes'][0]['target_node'],
|
|
"test_target_node")
|
|
self.assertEqual(
|
|
result['vcenter']['computes'][2]['target_node'],
|
|
"controllers")
|
|
|
|
|
|
class TestDeploymentAttributesSerializationSegmentationGre70(
|
|
TestDeploymentAttributesSerialization70
|
|
):
|
|
segmentation_type = consts.NEUTRON_SEGMENT_TYPES.gre
|
|
|
|
|
|
class TestDeploymentAttributesSerializationSegmentationTun70(
|
|
TestDeploymentAttributesSerialization70
|
|
):
|
|
segmentation_type = consts.NEUTRON_SEGMENT_TYPES.tun
|
|
|
|
|
|
class TestDeploymentSerializationForNovaNetwork70(
|
|
BaseTestDeploymentAttributesSerialization70
|
|
):
|
|
|
|
def create_env(self, mode):
|
|
release = self.patch_net_roles_for_release()
|
|
return self.env.create(
|
|
cluster_kwargs={
|
|
'release_id': release.id,
|
|
'mode': mode,
|
|
'net_provider': consts.CLUSTER_NET_PROVIDERS.nova_network},
|
|
nodes_kwargs=[
|
|
{'roles': ['controller'],
|
|
'pending_addition': True,
|
|
'name': self.node_name,
|
|
}
|
|
])
|
|
|
|
def test_network_scheme(self):
|
|
for node in self.serialized_for_astute:
|
|
roles = node['network_scheme']['roles']
|
|
expected_roles = {
|
|
'admin/pxe': 'br-fw-admin',
|
|
|
|
'keystone/api': 'br-mgmt',
|
|
'swift/api': 'br-mgmt',
|
|
'sahara/api': 'br-mgmt',
|
|
'ceilometer/api': 'br-mgmt',
|
|
'cinder/api': 'br-mgmt',
|
|
'glance/api': 'br-mgmt',
|
|
'heat/api': 'br-mgmt',
|
|
'nova/api': 'br-mgmt',
|
|
'murano/api': 'br-mgmt',
|
|
'horizon': 'br-mgmt',
|
|
|
|
'mgmt/database': 'br-mgmt',
|
|
'mgmt/messaging': 'br-mgmt',
|
|
'mgmt/corosync': 'br-mgmt',
|
|
'mgmt/memcache': 'br-mgmt',
|
|
'mgmt/vip': 'br-mgmt',
|
|
|
|
'public/vip': 'br-ex',
|
|
|
|
'swift/replication': 'br-storage',
|
|
|
|
'ceph/public': 'br-mgmt',
|
|
'ceph/radosgw': 'br-ex',
|
|
'ceph/replication': 'br-storage',
|
|
|
|
'cinder/iscsi': 'br-storage',
|
|
|
|
'mongo/db': 'br-mgmt',
|
|
|
|
'novanetwork/fixed': 'eth0.103',
|
|
|
|
# deprecated
|
|
'fw-admin': 'br-fw-admin',
|
|
'management': 'br-mgmt',
|
|
'ex': 'br-ex',
|
|
'storage': 'br-storage',
|
|
}
|
|
self.assertEqual(roles, expected_roles)
|
|
|
|
def test_network_metadata(self):
|
|
nm = objects.Cluster.get_network_manager(self.cluster)
|
|
ip_by_net = {
|
|
'fuelweb_admin': None,
|
|
'storage': None,
|
|
'management': None,
|
|
'public': None
|
|
}
|
|
node = self.env.nodes[0]
|
|
networks = nm.get_node_networks(node)
|
|
for net in ip_by_net:
|
|
netgroup = nm.get_network_by_netname(net, networks)
|
|
if netgroup.get('ip'):
|
|
ip_by_net[net] = netgroup['ip'].split('/')[0]
|
|
for node_data in self.serialized_for_astute:
|
|
self.assertItemsEqual(
|
|
node_data['network_metadata'], ['nodes', 'vips'])
|
|
nodes = node_data['network_metadata']['nodes']
|
|
for node_name, node_attrs in nodes.items():
|
|
self.assertItemsEqual(
|
|
node_attrs,
|
|
['uid', 'fqdn', 'name', 'user_node_name',
|
|
'swift_zone', 'node_roles', 'network_roles']
|
|
)
|
|
self.assertEqual(objects.Node.get_slave_name(node), node_name)
|
|
self.assertEqual(node_attrs['uid'], node.uid)
|
|
self.assertEqual(node_attrs['fqdn'],
|
|
objects.Node.get_node_fqdn(node))
|
|
self.assertEqual(node_attrs['name'], node_name)
|
|
self.assertEqual(node_attrs['user_node_name'], node.name)
|
|
self.assertEqual(node_attrs['swift_zone'], node.uid)
|
|
|
|
network_roles = {
|
|
'admin/pxe': ip_by_net['fuelweb_admin'],
|
|
'fw-admin': ip_by_net['fuelweb_admin'],
|
|
|
|
'keystone/api': ip_by_net['management'],
|
|
'swift/api': ip_by_net['management'],
|
|
'sahara/api': ip_by_net['management'],
|
|
'ceilometer/api': ip_by_net['management'],
|
|
'cinder/api': ip_by_net['management'],
|
|
'glance/api': ip_by_net['management'],
|
|
'heat/api': ip_by_net['management'],
|
|
'nova/api': ip_by_net['management'],
|
|
'murano/api': ip_by_net['management'],
|
|
'horizon': ip_by_net['management'],
|
|
|
|
'management': ip_by_net['management'],
|
|
'mgmt/database': ip_by_net['management'],
|
|
'mgmt/messaging': ip_by_net['management'],
|
|
'mgmt/corosync': ip_by_net['management'],
|
|
'mgmt/memcache': ip_by_net['management'],
|
|
'mgmt/vip': ip_by_net['management'],
|
|
|
|
'mongo/db': ip_by_net['management'],
|
|
|
|
'ceph/public': ip_by_net['management'],
|
|
|
|
'storage': ip_by_net['storage'],
|
|
'ceph/replication': ip_by_net['storage'],
|
|
'swift/replication': ip_by_net['storage'],
|
|
'cinder/iscsi': ip_by_net['storage'],
|
|
|
|
'ex': ip_by_net['public'],
|
|
'public/vip': ip_by_net['public'],
|
|
'ceph/radosgw': ip_by_net['public'],
|
|
}
|
|
self.assertEqual(
|
|
node_attrs['network_roles'],
|
|
network_roles
|
|
)
|
|
self.check_vips_serialized(node_data)
|
|
|
|
def test_generate_vmware_attributes_data(self):
|
|
self.check_generate_vmware_attributes_data()
|
|
|
|
result = self.serializer.serialize_node(
|
|
self.env.nodes[0], 'compute-vmware'
|
|
)
|
|
|
|
self.assertEqual(
|
|
result['vcenter']['computes'][0]['target_node'],
|
|
"test_target_node")
|
|
self.assertEqual(
|
|
result['vcenter']['computes'][2]['target_node'],
|
|
"controllers")
|
|
|
|
|
|
class TestPluginDeploymentTasksInjection70(base.BaseIntegrationTest):
|
|
env_version = '2015.1.0-7.0'
|
|
|
|
release_deployment_tasks = [
|
|
{'id': 'pre_deployment_start',
|
|
'type': 'stage'},
|
|
{'id': 'pre_deployment_end',
|
|
'type': 'stage',
|
|
'requires': ['pre_deployment_start']},
|
|
{'id': 'deploy_start',
|
|
'type': 'stage'},
|
|
{'id': 'deploy_end',
|
|
'requires': ['deploy_start'],
|
|
'type': 'stage'},
|
|
{'id': 'post_deployment_start',
|
|
'type': 'stage',
|
|
'requires': ['deploy_end']},
|
|
{'id': 'post_deployment_end',
|
|
'type': 'stage',
|
|
'requires': ['post_deployment_start']},
|
|
{'id': 'primary-controller',
|
|
'parameters': {'strategy': {'type': 'one_by_one'}},
|
|
'required_for': ['deploy_end'],
|
|
'requires': ['deploy_start'],
|
|
'role': ['primary-controller'],
|
|
'type': 'group'},
|
|
{'id': 'first-fake-depl-task',
|
|
'required_for': ['deploy_end'],
|
|
'requires': ['deploy_start'],
|
|
'type': 'puppet',
|
|
'parameters': {'puppet_manifest': 'first-fake-depl-task',
|
|
'puppet_modules': 'test',
|
|
'timeout': 0},
|
|
'groups': ['primary-controller']},
|
|
{'id': 'second-fake-depl-task',
|
|
'required_for': ['deploy_end'],
|
|
'requires': ['deploy_start'],
|
|
'type': 'puppet',
|
|
'parameters': {'puppet_manifest': 'second-fake-depl-task',
|
|
'puppet_modules': 'test',
|
|
'timeout': 0},
|
|
'groups': ['primary-controller']},
|
|
]
|
|
|
|
def setUp(self):
|
|
super(TestPluginDeploymentTasksInjection70, self).setUp()
|
|
# Plugin task injection for Task based is checked in task based tests
|
|
self.cluster = self.env.create(
|
|
release_kwargs={
|
|
'deployment_tasks': self.release_deployment_tasks,
|
|
'version': self.env_version
|
|
},
|
|
cluster_kwargs={
|
|
'mode': consts.CLUSTER_MODES.ha_compact,
|
|
'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
|
|
'net_segment_type': consts.NEUTRON_SEGMENT_TYPES.vlan,
|
|
},
|
|
nodes_kwargs=[
|
|
{'roles': ['controller'], 'primary_tags': ['controller'],
|
|
'pending_addition': True}
|
|
]
|
|
)
|
|
|
|
objects.Cluster.set_primary_tags(self.cluster, self.cluster.nodes)
|
|
self.plugin_data = {
|
|
'package_version': '3.0.0',
|
|
'releases': [
|
|
{
|
|
'repository_path': 'plugin_test',
|
|
'version': self.cluster.release.version,
|
|
'os': self.cluster.release.operating_system.lower(),
|
|
'mode': ['ha', 'multinode'],
|
|
'deployment_scripts_path': 'plugin_test/'
|
|
},
|
|
],
|
|
}
|
|
|
|
def prepare_plugins_for_cluster(self, cluster, plugins_kw_list):
|
|
for kw in plugins_kw_list:
|
|
kw.update(self.plugin_data)
|
|
self.env.create_plugin(cluster=cluster, **kw)
|
|
|
|
def _check_pre_deployment_tasks(self, serialized, task_type):
|
|
self.assertTrue(serialized)
|
|
|
|
needed_task = next(
|
|
t for t in serialized
|
|
if t['type'] == task_type)
|
|
self.assertIsNotNone(needed_task)
|
|
self.assertIsNotNone(needed_task.get('parameters'))
|
|
self.assertItemsEqual(
|
|
(n.uid for n in self.cluster.nodes),
|
|
needed_task['uids']
|
|
)
|
|
|
|
def test_plugin_depl_tasks_proper_injections(self):
|
|
self.prepare_plugins_for_cluster(
|
|
self.cluster,
|
|
[
|
|
{
|
|
'name': 'between_rel_tasks',
|
|
'deployment_tasks': [
|
|
{
|
|
'id': 'between-rel-tasks',
|
|
'type': 'puppet',
|
|
'groups': ['primary-controller'],
|
|
'requires': ['first-fake-depl-task'],
|
|
'required_for': ['second-fake-depl-task'],
|
|
'parameters': {
|
|
'puppet_manifest': 'between-rel-tasks',
|
|
'puppet_modules': 'test',
|
|
'timeout': 0,
|
|
}
|
|
},
|
|
],
|
|
},
|
|
]
|
|
)
|
|
|
|
graph = AstuteGraph(self.cluster)
|
|
objects.Cluster.prepare_for_deployment(self.cluster)
|
|
serializer = \
|
|
get_serializer_for_cluster(self.cluster)(graph)
|
|
serialized = serializer.serialize(self.cluster, self.cluster.nodes)
|
|
serialized = deployment_info_to_legacy(serialized)
|
|
|
|
serialized_tasks = serialized[0]['tasks']
|
|
|
|
expected_priority = {
|
|
100: 'first-fake-depl-task',
|
|
200: 'between-rel-tasks',
|
|
300: 'second-fake-depl-task',
|
|
}
|
|
|
|
for task in serialized_tasks:
|
|
task_identificator = task['parameters']['puppet_manifest']
|
|
self.assertEqual(
|
|
task_identificator, expected_priority[task['priority']]
|
|
)
|
|
|
|
def test_plugin_depl_task_overwrite_from_rel(self):
|
|
self.prepare_plugins_for_cluster(
|
|
self.cluster,
|
|
[
|
|
{
|
|
'name': 'between_rel_tasks',
|
|
'deployment_tasks': [
|
|
{
|
|
'id': 'first-fake-depl-task',
|
|
'type': 'puppet',
|
|
'groups': ['primary-controller'],
|
|
'requires': ['deploy_start'],
|
|
'required_for': ['second-fake-depl-task'],
|
|
'parameters': {
|
|
'puppet_manifest': 'plugin_task',
|
|
'puppet_modules': 'test',
|
|
'timeout': 0,
|
|
}
|
|
},
|
|
],
|
|
},
|
|
]
|
|
)
|
|
|
|
graph = AstuteGraph(self.cluster)
|
|
objects.Cluster.prepare_for_deployment(self.cluster)
|
|
serializer = \
|
|
get_serializer_for_cluster(self.cluster)(graph)
|
|
serialized = serializer.serialize(self.cluster, self.cluster.nodes)
|
|
serialized = deployment_info_to_legacy(serialized)
|
|
|
|
serialized_tasks = serialized[0]['tasks']
|
|
|
|
needed_task_priority = next(
|
|
t['priority'] for t in serialized_tasks
|
|
if t['parameters']['puppet_manifest'] == 'plugin_task'
|
|
)
|
|
# first task in graph has priority equal 100
|
|
self.assertEqual(needed_task_priority, 100)
|
|
|
|
def test_plugin_depl_task_in_pre_depl(self):
|
|
self.prepare_plugins_for_cluster(
|
|
self.cluster,
|
|
[
|
|
{
|
|
'name': 'pre_depl_plugin_task',
|
|
'deployment_tasks': [
|
|
{
|
|
'id': 'pre-depl-plugin-task',
|
|
'type': 'puppet',
|
|
'role': ['primary-controller'],
|
|
'requires': ['pre_deployment_start'],
|
|
'required_for': ['pre_deployment_end'],
|
|
'parameters': {
|
|
'puppet_manifest': 'pre_depl_plugin_task',
|
|
'puppet_modules': 'test',
|
|
'timeout': 0,
|
|
}
|
|
},
|
|
],
|
|
},
|
|
]
|
|
)
|
|
|
|
graph = AstuteGraph(self.cluster)
|
|
objects.Cluster.prepare_for_deployment(self.cluster)
|
|
with mock.patch('nailgun.plugins.adapters.glob.glob',
|
|
mock.Mock(return_value='path/to/test/repos')):
|
|
pre_deployment = stages.pre_deployment_serialize(
|
|
graph, self.cluster, self.cluster.nodes)
|
|
|
|
for task_type in (consts.ORCHESTRATOR_TASK_TYPES.sync,
|
|
consts.ORCHESTRATOR_TASK_TYPES.upload_file):
|
|
self._check_pre_deployment_tasks(pre_deployment, task_type)
|
|
|
|
def test_plugin_depl_task_for_master_not_in_pre_depl(self):
|
|
self.prepare_plugins_for_cluster(
|
|
self.cluster,
|
|
[
|
|
{
|
|
'name': 'pre_depl_plugin_task',
|
|
'deployment_tasks': [
|
|
{
|
|
'id': 'pre-depl-plugin-task',
|
|
'type': 'puppet',
|
|
'role': consts.MASTER_NODE_UID,
|
|
'requires': ['pre_deployment_start'],
|
|
'required_for': ['pre_deployment_end'],
|
|
'parameters': {
|
|
'puppet_manifest': 'pre_depl_plugin_task',
|
|
'puppet_modules': 'test',
|
|
'timeout': 0,
|
|
}
|
|
},
|
|
],
|
|
},
|
|
{
|
|
'name': 'pre_depl_plugin_task_for_master_and_contr',
|
|
'deployment_tasks': [
|
|
{
|
|
'id': 'pre-depl-plugin-task-for-master-and-contr',
|
|
'type': 'puppet',
|
|
'groups': [consts.MASTER_NODE_UID,
|
|
'primary-controller'],
|
|
'requires': ['pre_deployment_start'],
|
|
'required_for': ['pre_deployment_end'],
|
|
'parameters': {
|
|
'puppet_manifest': 'pre_depl_plugin_task',
|
|
'puppet_modules': 'test',
|
|
'timeout': 0,
|
|
}
|
|
},
|
|
],
|
|
},
|
|
]
|
|
)
|
|
|
|
graph = AstuteGraph(self.cluster)
|
|
objects.Cluster.prepare_for_deployment(self.cluster)
|
|
with mock.patch('nailgun.plugins.adapters.glob.glob',
|
|
mock.Mock(return_value='path/to/test/repos')):
|
|
pre_deployment = stages.pre_deployment_serialize(
|
|
graph, self.cluster, self.cluster.nodes)
|
|
|
|
for st in pre_deployment:
|
|
self.assertNotIn(consts.MASTER_NODE_UID, st['uids'])
|
|
|
|
def test_plugin_depl_task_in_post_depl(self):
|
|
self.prepare_plugins_for_cluster(
|
|
self.cluster,
|
|
[
|
|
{
|
|
'name': 'post-depl-plugin-task',
|
|
'deployment_tasks': [
|
|
{
|
|
'id': 'post-depl-plugin-task',
|
|
'type': 'puppet',
|
|
'role': ['primary-controller'],
|
|
'requires': ['post_deployment_start'],
|
|
'required_for': ['post_deployment_end'],
|
|
'parameters': {
|
|
'puppet_manifest': 'post_depl_plugin_task',
|
|
'puppet_modules': 'test',
|
|
'timeout': 0,
|
|
}
|
|
},
|
|
],
|
|
},
|
|
]
|
|
)
|
|
|
|
graph = AstuteGraph(self.cluster)
|
|
objects.Cluster.prepare_for_deployment(self.cluster)
|
|
post_deployment = stages.post_deployment_serialize(
|
|
graph, self.cluster, self.cluster.nodes)
|
|
|
|
self.assertEqual(
|
|
post_deployment[0]['parameters']['puppet_manifest'],
|
|
'post_depl_plugin_task'
|
|
)
|
|
|
|
def test_process_skipped_task(self):
|
|
self.prepare_plugins_for_cluster(
|
|
self.cluster,
|
|
[
|
|
{
|
|
'name': 'task_with_skipped_plugin',
|
|
'deployment_tasks': [
|
|
{
|
|
'id': 'skipped_task',
|
|
'type': 'skipped',
|
|
},
|
|
],
|
|
},
|
|
]
|
|
)
|
|
|
|
graph = AstuteGraph(self.cluster)
|
|
objects.Cluster.prepare_for_deployment(self.cluster)
|
|
serializer = \
|
|
get_serializer_for_cluster(self.cluster)(graph)
|
|
serialized = serializer.serialize(self.cluster, self.cluster.nodes)
|
|
serialized = deployment_info_to_legacy(serialized)
|
|
|
|
tasks = serialized[0]['tasks']
|
|
release_depl_tasks_ids = ('first-fake-depl-task',
|
|
'second-fake-depl-task')
|
|
|
|
serialized_tasks_ids = (t['parameters']['puppet_manifest']
|
|
for t in tasks)
|
|
self.assertItemsEqual(release_depl_tasks_ids, serialized_tasks_ids)
|
|
|
|
|
|
class TestRolesSerializationWithPlugins(BaseDeploymentSerializer,
|
|
PrepareDataMixin,
|
|
DeploymentTasksTestMixin):
|
|
|
|
env_version = '2015.1.0-7.0'
|
|
|
|
ROLES = yaml.safe_load("""
|
|
test_role:
|
|
name: "Some plugin role"
|
|
description: "Some description"
|
|
conflicts:
|
|
- some_not_compatible_role
|
|
limits:
|
|
min: 1
|
|
restrictions:
|
|
- condition: "some logic condition"
|
|
message: "Some message for restriction warning"
|
|
volumes_mapping:
|
|
- {allocate_size: "min", id: "os"}
|
|
- {allocate_size: "all", id: "role_volume_name"}
|
|
""")
|
|
|
|
DEPLOYMENT_TASKS = yaml.safe_load("""
|
|
- id: test_role
|
|
type: group
|
|
role: [test_role]
|
|
required_for: [deploy_end]
|
|
requires: [deploy_start]
|
|
parameters:
|
|
strategy:
|
|
type: one_by_one
|
|
|
|
- id: deployment_task_id
|
|
type: puppet
|
|
groups: [test_role]
|
|
required_for: [deploy_end]
|
|
requires: [deploy_start]
|
|
parameters:
|
|
puppet_manifest: /path/to/manifests
|
|
puppet_modules: /path/to/modules
|
|
timeout: 3600
|
|
""")
|
|
|
|
def setUp(self):
|
|
super(TestRolesSerializationWithPlugins, self).setUp()
|
|
|
|
release = self.patch_net_roles_for_release()
|
|
self.cluster = self.env.create(
|
|
cluster_kwargs={
|
|
'release_id': release.id,
|
|
'mode': consts.CLUSTER_MODES.ha_compact,
|
|
'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
|
|
'net_segment_type': consts.NEUTRON_SEGMENT_TYPES.vlan,
|
|
})
|
|
|
|
self.plugin_data = {
|
|
'package_version': '3.0.0',
|
|
'releases': [
|
|
{
|
|
'repository_path': 'repositories/ubuntu',
|
|
'version': self.cluster.release.version,
|
|
'os': self.cluster.release.operating_system.lower(),
|
|
'mode': [self.cluster.mode],
|
|
}
|
|
]
|
|
}
|
|
|
|
def test_tasks_were_serialized(self):
|
|
plugin_data = {
|
|
'roles_metadata': self.ROLES,
|
|
'deployment_tasks': self.DEPLOYMENT_TASKS
|
|
}
|
|
plugin_data.update(self.plugin_data)
|
|
self.env.create_plugin(cluster=self.cluster, **plugin_data)
|
|
|
|
self.env.create_node(
|
|
api=True,
|
|
cluster_id=self.cluster.id,
|
|
pending_roles=['test_role'],
|
|
pending_addition=True)
|
|
self.db.flush()
|
|
|
|
objects.Cluster.prepare_for_deployment(self.cluster)
|
|
|
|
serializer = self._get_serializer(self.cluster)
|
|
with mock.patch('nailgun.objects.node.Node.all_tags',
|
|
mock.Mock(return_value=['test_role'])):
|
|
serialized_data = serializer.serialize(
|
|
self.cluster, self.cluster.nodes)
|
|
serialized_data = deployment_info_to_legacy(serialized_data)
|
|
self.assertItemsEqual(serialized_data[0]['tasks'], [{
|
|
'parameters': {
|
|
'cwd': '/etc/fuel/plugins/testing_plugin-0.1/',
|
|
'puppet_manifest': '/path/to/manifests',
|
|
'puppet_modules': '/path/to/modules',
|
|
'timeout': 3600,
|
|
'retries': None,
|
|
},
|
|
'priority': 100,
|
|
'type': 'puppet',
|
|
'uids': [self.cluster.nodes[0].uid],
|
|
'id': 'deployment_task_id'
|
|
}])
|
|
|
|
def test_tasks_were_not_serialized(self):
|
|
plugin_data = {
|
|
'roles_metadata': {},
|
|
'deployment_tasks': self.DEPLOYMENT_TASKS
|
|
}
|
|
plugin_data.update(self.plugin_data)
|
|
self.env.create_plugin(cluster=self.cluster, **plugin_data)
|
|
|
|
self.env.create_node(
|
|
api=True,
|
|
cluster_id=self.cluster.id,
|
|
pending_roles=['controller'],
|
|
pending_addition=True)
|
|
self.db.flush()
|
|
|
|
objects.Cluster.prepare_for_deployment(self.cluster)
|
|
|
|
serializer = self._get_serializer(self.cluster)
|
|
serialized_data = serializer.serialize(
|
|
self.cluster, self.cluster.nodes)
|
|
serialized_data = deployment_info_to_legacy(serialized_data)
|
|
self.maxDiff = None
|
|
|
|
self._compare_tasks([
|
|
{
|
|
'parameters': {
|
|
'puppet_modules': '/etc/puppet/modules',
|
|
'puppet_manifest': '/etc/puppet/modules/osnailyfacter/'
|
|
'modular/netconfig/netconfig.pp',
|
|
'timeout': 3600,
|
|
'retries': None,
|
|
'cwd': '/'},
|
|
'priority': 100,
|
|
'type': 'puppet',
|
|
'id': 'netconfig',
|
|
'uids': [self.cluster.nodes[0].uid],
|
|
}, {
|
|
'parameters': {
|
|
'cwd': '/',
|
|
'puppet_manifest': '/etc/puppet/manifests/site.pp',
|
|
'puppet_modules': '/etc/puppet/modules',
|
|
'timeout': 3600,
|
|
'retries': None},
|
|
'priority': 200,
|
|
'type': 'puppet',
|
|
'id': 'deploy_legacy',
|
|
'uids': [self.cluster.nodes[0].uid],
|
|
}, {
|
|
'parameters': {
|
|
'puppet_modules': '/etc/puppet/modules',
|
|
'puppet_manifest': '/etc/puppet/modules/osnailyfacter/'
|
|
'modular/globals/globals.pp',
|
|
'timeout': 3600,
|
|
'retries': None,
|
|
'cwd': '/'},
|
|
'priority': 300,
|
|
'type': 'puppet',
|
|
'id': 'globals',
|
|
'uids': [self.cluster.nodes[0].uid],
|
|
}], serialized_data[0]['tasks'])
|
|
|
|
|
|
class TestNetworkTemplateSerializer70(BaseDeploymentSerializer,
|
|
PrepareDataMixin):
|
|
|
|
env_version = '2015.1.0-7.0'
|
|
general_serializer = NeutronNetworkDeploymentSerializer70
|
|
template_serializer = NeutronNetworkTemplateSerializer70
|
|
|
|
def setUp(self, *args):
|
|
super(TestNetworkTemplateSerializer70, self).setUp()
|
|
self.cluster = self.create_env(consts.NEUTRON_SEGMENT_TYPES.vlan)
|
|
self.net_template = self.env.read_fixtures(['network_template_70'])[0]
|
|
|
|
objects.Cluster.set_network_template(
|
|
self.cluster,
|
|
self.net_template
|
|
)
|
|
cluster_db = self.db.query(models.Cluster).get(self.cluster['id'])
|
|
objects.Cluster.prepare_for_deployment(cluster_db)
|
|
serializer = self._get_serializer(self.cluster)
|
|
self.serialized_for_astute = serializer.serialize(self.cluster,
|
|
cluster_db.nodes)
|
|
self.serialized_for_astute = deployment_info_to_legacy(
|
|
self.serialized_for_astute)
|
|
|
|
def create_env(self, segment_type):
|
|
release = self.patch_net_roles_for_release()
|
|
cluster = self.env.create(
|
|
cluster_kwargs={
|
|
'api': False,
|
|
'release_id': release.id,
|
|
'mode': consts.CLUSTER_MODES.ha_compact,
|
|
'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
|
|
'net_segment_type': segment_type},
|
|
)
|
|
nodes_kwargs = {
|
|
'roles': ['controller'],
|
|
'pending_addition': True,
|
|
'name': self.node_name,
|
|
'cluster_id': cluster['id']
|
|
}
|
|
self.env.create_nodes_w_interfaces_count(1, 6, **nodes_kwargs)
|
|
nodes_kwargs['roles'] = ['compute', 'cinder']
|
|
self.env.create_nodes_w_interfaces_count(1, 6, **nodes_kwargs)
|
|
|
|
return cluster
|
|
|
|
def create_more_nodes(self, iface_count=3):
|
|
self.env.create_nodes_w_interfaces_count(
|
|
1, iface_count, roles=['cinder'], cluster_id=self.cluster.id)
|
|
self.env.create_nodes_w_interfaces_count(
|
|
1, iface_count,
|
|
roles=['cinder', 'controller'], cluster_id=self.cluster.id)
|
|
self.env.create_nodes_w_interfaces_count(
|
|
1, iface_count, roles=['compute'], cluster_id=self.cluster.id)
|
|
|
|
def check_node_ips_on_certain_networks(self, node, net_names):
|
|
ips = db().query(models.IPAddr).filter_by(node=node.id)
|
|
self.assertEqual(ips.count(), len(net_names))
|
|
for ip in ips:
|
|
self.assertIn(ip.network_data.name, net_names)
|
|
|
|
def test_get_net_provider_serializer(self):
|
|
serializer = get_serializer_for_cluster(self.cluster)
|
|
self.cluster.network_config.configuration_template = None
|
|
|
|
net_serializer = serializer.get_net_provider_serializer(self.cluster)
|
|
self.assertIs(net_serializer, self.general_serializer)
|
|
|
|
self.cluster.network_config.configuration_template = \
|
|
self.net_template
|
|
net_serializer = serializer.get_net_provider_serializer(self.cluster)
|
|
self.assertIs(net_serializer, self.template_serializer)
|
|
|
|
def test_ip_assignment_according_to_template(self):
|
|
self.create_more_nodes(iface_count=4)
|
|
# according to the template different node roles have different sets of
|
|
# networks
|
|
node_roles_vs_net_names = [
|
|
(['controller'], ['public', 'management', 'fuelweb_admin']),
|
|
(['compute'], ['management', 'fuelweb_admin']),
|
|
(['cinder'], ['storage', 'management', 'fuelweb_admin']),
|
|
(['compute', 'cinder'],
|
|
['storage', 'management', 'fuelweb_admin']),
|
|
(['controller', 'cinder'],
|
|
['public', 'storage', 'management', 'fuelweb_admin'])]
|
|
|
|
template_meta = self.net_template["adv_net_template"]["default"]
|
|
# wipe out 'storage' template for 'compute' node role to make
|
|
# node roles more distinct
|
|
for node_role, template_list in six.iteritems(
|
|
template_meta["templates_for_node_role"]):
|
|
if node_role == 'compute':
|
|
template_list.remove('storage')
|
|
|
|
objects.Cluster.set_network_template(
|
|
self.cluster,
|
|
self.net_template
|
|
)
|
|
cluster_db = objects.Cluster.get_by_uid(self.cluster['id'])
|
|
objects.Cluster.prepare_for_deployment(cluster_db)
|
|
serializer = self._get_serializer(self.cluster)
|
|
serialized_for_astute = serializer.serialize(self.cluster,
|
|
cluster_db.nodes)
|
|
serialized_for_astute = self._handle_facts(
|
|
deployment_info_to_legacy(serialized_for_astute)
|
|
)
|
|
|
|
nodes_count = self._get_nodes_count_in_astute_info(self.cluster.nodes)
|
|
self.assertEqual(len(serialized_for_astute), nodes_count)
|
|
for node_data in serialized_for_astute:
|
|
node = objects.Node.get_by_uid(node_data['uid'])
|
|
for node_roles, net_names in node_roles_vs_net_names:
|
|
if node.all_roles == set(node_roles):
|
|
self.check_node_ips_on_certain_networks(node, net_names)
|
|
break
|
|
else:
|
|
self.fail("Unexpected combination of node roles: {0}".format(
|
|
node.all_roles))
|
|
|
|
def test_gateway_not_set_for_none_ip(self):
|
|
attrs = copy.deepcopy(self.cluster.attributes.editable)
|
|
attrs['neutron_advanced_configuration']['neutron_dvr']['value'] = True
|
|
resp = self.app.patch(
|
|
reverse(
|
|
'ClusterAttributesHandler',
|
|
kwargs={'cluster_id': self.cluster.id}),
|
|
params=jsonutils.dumps({'editable': attrs}),
|
|
headers=self.default_headers
|
|
)
|
|
self.assertEqual(200, resp.status_code)
|
|
self.assertTrue(objects.Cluster.neutron_dvr_enabled(self.cluster))
|
|
|
|
objects.Cluster.set_network_template(self.cluster, None)
|
|
|
|
computes = filter(lambda n: 'compute' in n.roles, self.cluster.nodes)
|
|
self.assertTrue(len(computes) > 0)
|
|
compute = computes[0]
|
|
|
|
serializer = get_serializer_for_cluster(self.cluster)
|
|
net_serializer = serializer.get_net_provider_serializer(self.cluster)
|
|
self.assertIs(net_serializer, self.general_serializer)
|
|
|
|
nm = objects.Cluster.get_network_manager(self.cluster)
|
|
networks = nm.get_node_networks(compute)
|
|
|
|
self.assertFalse(objects.Node.should_have_public_with_ip(compute))
|
|
network_scheme = net_serializer.generate_network_scheme(
|
|
compute, networks)
|
|
self.assertNotIn('gateway', network_scheme['endpoints']['br-ex'])
|
|
self.assertEqual('none', network_scheme['endpoints']['br-ex']['IP'])
|
|
|
|
def test_public_iface_added_to_br_ex_in_dvr(self):
|
|
attrs = copy.deepcopy(self.cluster.attributes.editable)
|
|
attrs['neutron_advanced_configuration']['neutron_dvr']['value'] = True
|
|
resp = self.app.patch(
|
|
reverse(
|
|
'ClusterAttributesHandler',
|
|
kwargs={'cluster_id': self.cluster.id}),
|
|
params=jsonutils.dumps({'editable': attrs}),
|
|
headers=self.default_headers
|
|
)
|
|
self.assertEqual(200, resp.status_code)
|
|
self.assertTrue(objects.Cluster.neutron_dvr_enabled(self.cluster))
|
|
|
|
objects.Cluster.set_network_template(self.cluster, None)
|
|
|
|
computes = filter(lambda n: 'compute' in n.roles, self.cluster.nodes)
|
|
self.assertTrue(len(computes) > 0)
|
|
compute = computes[0]
|
|
|
|
serializer = get_serializer_for_cluster(self.cluster)
|
|
net_serializer = serializer.get_net_provider_serializer(self.cluster)
|
|
self.assertIs(net_serializer, self.general_serializer)
|
|
|
|
nm = objects.Cluster.get_network_manager(self.cluster)
|
|
networks = nm.get_node_networks(compute)
|
|
public_net = next((net for net in networks if net['name'] == 'public'),
|
|
None)
|
|
self.assertIsNotNone(public_net)
|
|
|
|
self.assertFalse(objects.Node.should_have_public_with_ip(compute))
|
|
network_scheme = net_serializer.generate_network_scheme(
|
|
compute, networks)
|
|
expected = {'action': 'add-port',
|
|
'bridge': 'br-ex',
|
|
'name': public_net['dev']}
|
|
self.assertIn(expected, network_scheme['transformations'])
|
|
|
|
def test_replacements_in_network_assignments(self):
|
|
|
|
node_roles_vs_net_names = [
|
|
(['controller'], ['public', 'management', 'fuelweb_admin']),
|
|
(['compute', 'cinder'],
|
|
['storage', 'management', 'fuelweb_admin'])]
|
|
|
|
template_meta = self.net_template["adv_net_template"]["default"]
|
|
|
|
iface_var = template_meta['nic_mapping']['default'].keys()[0]
|
|
|
|
ep_with_var = "<% {0} %>.123".format(iface_var)
|
|
|
|
template_meta['network_assignments']['storage']['ep'] = ep_with_var
|
|
template_meta['network_scheme']['storage']['endpoints'] = \
|
|
[ep_with_var]
|
|
|
|
objects.Cluster.set_network_template(
|
|
self.cluster,
|
|
self.net_template
|
|
)
|
|
cluster_db = objects.Cluster.get_by_uid(self.cluster['id'])
|
|
objects.Cluster.prepare_for_deployment(cluster_db)
|
|
|
|
serializer = self._get_serializer(self.cluster)
|
|
serialized_for_astute = serializer.serialize(self.cluster,
|
|
cluster_db.nodes)
|
|
serialized_for_astute = self._handle_facts(
|
|
deployment_info_to_legacy(serialized_for_astute)
|
|
)
|
|
|
|
for node_data in serialized_for_astute:
|
|
node = objects.Node.get_by_uid(node_data['uid'])
|
|
for node_roles, net_names in node_roles_vs_net_names:
|
|
if node.all_roles == set(node_roles):
|
|
self.check_node_ips_on_certain_networks(node, net_names)
|
|
break
|
|
else:
|
|
self.fail("Unexpected combination of node roles: {0}".format(
|
|
node.all_roles))
|
|
|
|
def test_multiple_node_roles_network_roles(self):
|
|
expected_roles = {
|
|
# controller node
|
|
objects.Node.get_node_fqdn(self.cluster.nodes[0]): {
|
|
'management': 'br-mgmt',
|
|
'admin/pxe': 'br-fw-admin',
|
|
'swift/api': 'br-mgmt',
|
|
'neutron/api': 'br-mgmt',
|
|
'sahara/api': 'br-mgmt',
|
|
'ceilometer/api': 'br-mgmt',
|
|
'cinder/api': 'br-mgmt',
|
|
'keystone/api': 'br-mgmt',
|
|
'glance/api': 'br-mgmt',
|
|
'heat/api': 'br-mgmt',
|
|
'nova/api': 'br-mgmt',
|
|
'murano/api': 'br-mgmt',
|
|
'horizon': 'br-mgmt',
|
|
'mgmt/memcache': 'br-mgmt',
|
|
'mgmt/database': 'br-mgmt',
|
|
'ceph/public': 'br-mgmt',
|
|
'public/vip': 'br-ex',
|
|
'swift/public': 'br-ex',
|
|
'neutron/floating': 'br-floating',
|
|
'ceph/radosgw': 'br-ex',
|
|
'mgmt/messaging': 'br-mgmt',
|
|
'neutron/mesh': 'br-mgmt',
|
|
'mgmt/vip': 'br-mgmt',
|
|
'mgmt/corosync': 'br-mgmt',
|
|
'mongo/db': 'br-mgmt',
|
|
'nova/migration': 'br-mgmt',
|
|
'fw-admin': 'br-fw-admin',
|
|
'ex': 'br-ex'
|
|
},
|
|
# compute/cinder node
|
|
objects.Node.get_node_fqdn(self.cluster.nodes[1]): {
|
|
'management': 'br-mgmt',
|
|
'admin/pxe': 'br-fw-admin',
|
|
'swift/api': 'br-mgmt',
|
|
'neutron/api': 'br-mgmt',
|
|
'sahara/api': 'br-mgmt',
|
|
'ceilometer/api': 'br-mgmt',
|
|
'cinder/api': 'br-mgmt',
|
|
'keystone/api': 'br-mgmt',
|
|
'glance/api': 'br-mgmt',
|
|
'heat/api': 'br-mgmt',
|
|
'nova/api': 'br-mgmt',
|
|
'murano/api': 'br-mgmt',
|
|
'horizon': 'br-mgmt',
|
|
'mgmt/memcache': 'br-mgmt',
|
|
'mgmt/database': 'br-mgmt',
|
|
'ceph/public': 'br-mgmt',
|
|
'cinder/iscsi': 'br-storage',
|
|
'swift/replication': 'br-storage',
|
|
'ceph/replication': 'br-storage',
|
|
'neutron/private': 'br-prv',
|
|
'mgmt/messaging': 'br-mgmt',
|
|
'neutron/mesh': 'br-mgmt',
|
|
'mgmt/vip': 'br-mgmt',
|
|
'mgmt/corosync': 'br-mgmt',
|
|
'mongo/db': 'br-mgmt',
|
|
'nova/migration': 'br-mgmt',
|
|
'fw-admin': 'br-fw-admin',
|
|
'storage': 'br-storage'
|
|
}
|
|
}
|
|
|
|
for node in self._handle_facts(self.serialized_for_astute):
|
|
roles = node['network_scheme']['roles']
|
|
self.assertEqual(roles, expected_roles[node['fqdn']])
|
|
|
|
def test_routes_while_using_multiple_node_groups(self):
|
|
self.env.create_node_group()
|
|
objects.Cluster.prepare_for_deployment(self.cluster)
|
|
serializer = self._get_serializer(self.cluster)
|
|
facts = serializer.serialize(
|
|
self.cluster, self.cluster.nodes)
|
|
facts = self._handle_facts(
|
|
deployment_info_to_legacy(facts)
|
|
)
|
|
|
|
for node in facts:
|
|
node_db = objects.Node.get_by_uid(node['uid'])
|
|
is_public = objects.Node.should_have_public(node_db)
|
|
endpoints = node['network_scheme']['endpoints']
|
|
if 'compute' in node_db.roles:
|
|
# private network won't have routes
|
|
self.assertEqual(endpoints['br-prv'], {'IP': 'none'})
|
|
endpoints.pop('br-prv')
|
|
else:
|
|
self.assertNotIn('br-prv', endpoints)
|
|
if is_public:
|
|
# floating network won't have routes
|
|
self.assertEqual(endpoints['br-floating'], {'IP': 'none'})
|
|
endpoints.pop('br-floating')
|
|
for name, descr in six.iteritems(endpoints):
|
|
self.assertTrue({'IP', 'routes'}.issubset(descr))
|
|
# the only route in this case is for Admin network
|
|
# others are shared
|
|
self.assertIn(len(descr['routes']), [0, 1])
|
|
if descr['routes']:
|
|
self.assertEqual(name, 'br-fw-admin')
|
|
for route in descr['routes']:
|
|
self.assertItemsEqual(['net', 'via'], route)
|
|
|
|
def test_multiple_node_roles_transformations(self):
|
|
node = self.cluster.nodes[1]
|
|
|
|
serializer = get_serializer_for_cluster(self.cluster)
|
|
net_serializer = serializer.get_net_provider_serializer(self.cluster)
|
|
|
|
transformations = net_serializer.generate_transformations(node)
|
|
|
|
# Two node roles with the same template should only generate one
|
|
# transformation.
|
|
admin_brs = filter(lambda t: t.get('name') == 'br-fw-admin',
|
|
transformations)
|
|
self.assertEqual(1, len(admin_brs))
|
|
|
|
# Templates are applied in the order as defined in the template.
|
|
# storage network template is applied after the 4 transformations
|
|
# in common
|
|
self.assertEqual('br-storage', transformations[4]['name'])
|
|
|
|
# Ensure all ports connected to br-mgmt happen after the bridge
|
|
# has been created
|
|
port_seen = False
|
|
for tx in transformations:
|
|
if tx.get('name') == 'br-mgmt' and tx['action'] == 'add-br' \
|
|
and port_seen:
|
|
self.fail('Port was added to br-mgmt prior to the bridge '
|
|
'being created')
|
|
if tx.get('bridge') == 'br-mgmt' and tx['action'] == 'add-port':
|
|
port_seen = True
|
|
|
|
def test_multiple_node_roles_network_metadata_attrs(self):
|
|
for node_data in self.serialized_for_astute:
|
|
self.assertItemsEqual(
|
|
node_data['network_metadata'], ['nodes', 'vips'])
|
|
nodes = node_data['network_metadata']['nodes']
|
|
for node_name, node_attrs in nodes.items():
|
|
self.assertItemsEqual(
|
|
node_attrs,
|
|
['uid', 'fqdn', 'name', 'user_node_name',
|
|
'swift_zone', 'node_roles', 'network_roles']
|
|
)
|
|
node = objects.Node.get_by_uid(node_attrs['uid'])
|
|
self.assertEqual(objects.Node.get_slave_name(node), node_name)
|
|
self.assertEqual(node_attrs['uid'], node.uid)
|
|
self.assertEqual(node_attrs['fqdn'],
|
|
objects.Node.get_node_fqdn(node))
|
|
self.assertEqual(node_attrs['name'], node_name)
|
|
self.assertEqual(node_attrs['user_node_name'], node.name)
|
|
self.assertEqual(node_attrs['swift_zone'], node.uid)
|
|
|
|
def test_multiple_node_roles_network_metadata_roles(self):
|
|
nm = objects.Cluster.get_network_manager(self.cluster)
|
|
ip_by_net = {}
|
|
for node_data in self.serialized_for_astute:
|
|
nodes = node_data['network_metadata']['nodes']
|
|
for node_name, node_attrs in nodes.items():
|
|
node = objects.Node.get_by_uid(node_attrs['uid'])
|
|
networks = nm.get_node_networks(node)
|
|
node_nets = [n['name'] for n in networks]
|
|
|
|
for net in node_nets:
|
|
netgroup = nm.get_network_by_netname(net, networks)
|
|
if netgroup.get('ip'):
|
|
ip_by_net[net] = netgroup['ip'].split('/')[0]
|
|
network_roles = {
|
|
'management': ip_by_net['management'],
|
|
'admin/pxe': ip_by_net['fuelweb_admin'],
|
|
'swift/api': ip_by_net['management'],
|
|
'neutron/api': ip_by_net['management'],
|
|
'sahara/api': ip_by_net['management'],
|
|
'ceilometer/api': ip_by_net['management'],
|
|
'cinder/api': ip_by_net['management'],
|
|
'keystone/api': ip_by_net['management'],
|
|
'glance/api': ip_by_net['management'],
|
|
'heat/api': ip_by_net['management'],
|
|
'nova/api': ip_by_net['management'],
|
|
'murano/api': ip_by_net['management'],
|
|
'horizon': ip_by_net['management'],
|
|
'mgmt/memcache': ip_by_net['management'],
|
|
'mgmt/database': ip_by_net['management'],
|
|
'mgmt/messaging': ip_by_net['management'],
|
|
'neutron/mesh': ip_by_net['management'],
|
|
'mgmt/vip': ip_by_net['management'],
|
|
'mgmt/corosync': ip_by_net['management'],
|
|
'mongo/db': ip_by_net['management'],
|
|
'nova/migration': ip_by_net['management'],
|
|
'ceph/public': ip_by_net['management'],
|
|
'fw-admin': ip_by_net['fuelweb_admin']
|
|
}
|
|
|
|
if node.all_roles == set(['controller']):
|
|
network_roles.update({
|
|
'public/vip': ip_by_net['public'],
|
|
'swift/public': ip_by_net['public'],
|
|
'neutron/floating': None,
|
|
'ceph/radosgw': ip_by_net['public'],
|
|
'ex': ip_by_net['public']
|
|
})
|
|
else:
|
|
network_roles.update({
|
|
'cinder/iscsi': ip_by_net['storage'],
|
|
'swift/replication': ip_by_net['storage'],
|
|
'ceph/replication': ip_by_net['storage'],
|
|
'storage': ip_by_net['storage'],
|
|
'neutron/private': None
|
|
})
|
|
self.assertEqual(
|
|
node_attrs['network_roles'],
|
|
network_roles
|
|
)
|
|
|
|
def test_delete_default_network_group(self):
|
|
net_name = "storage"
|
|
node_group = objects.Cluster.get_default_group(self.cluster)
|
|
# delete one of default network group
|
|
storage_net = objects.NetworkGroup.get_from_node_group_by_name(
|
|
node_group.id, net_name)
|
|
objects.NetworkGroup.delete(storage_net)
|
|
# download default template and fix it
|
|
net_template = self.env.read_fixtures(['network_template_70'])[0]
|
|
template_meta = net_template["adv_net_template"]["default"]
|
|
# wipe out network from template
|
|
del(template_meta["network_assignments"][net_name])
|
|
for k, v in six.iteritems(template_meta["templates_for_node_role"]):
|
|
if net_name in v:
|
|
v.remove(net_name)
|
|
del(template_meta["network_scheme"][net_name])
|
|
# apply updated template to the cluster
|
|
objects.Cluster.set_network_template(
|
|
self.cluster,
|
|
net_template
|
|
)
|
|
serializer = get_serializer_for_cluster(self.cluster)
|
|
net_serializer = serializer.get_net_provider_serializer(self.cluster)
|
|
# serializer should not fail if we delete one of default network
|
|
# what is not used in template
|
|
net_serializer.generate_network_metadata(self.cluster)
|
|
|
|
def test_network_not_mapped_to_nics_w_template(self):
|
|
# delete and restore management network to break the default
|
|
# networks to interfaces mapping
|
|
resp = self.app.get(
|
|
reverse('NetworkGroupCollectionHandler',
|
|
kwargs=self.cluster),
|
|
headers=self.default_headers,
|
|
expect_errors=False
|
|
)
|
|
management = None
|
|
for ng in jsonutils.loads(resp.body):
|
|
if ng['name'] == 'management':
|
|
management = ng
|
|
break
|
|
self.app.delete(
|
|
reverse(
|
|
'NetworkGroupHandler',
|
|
kwargs={'obj_id': management.pop('id')}
|
|
),
|
|
headers=self.default_headers
|
|
)
|
|
self.app.post(
|
|
reverse('NetworkGroupCollectionHandler'),
|
|
jsonutils.dumps(management),
|
|
headers=self.default_headers,
|
|
expect_errors=False,
|
|
)
|
|
resp = self.app.get(
|
|
reverse('NetworkGroupCollectionHandler',
|
|
kwargs=self.cluster),
|
|
headers=self.default_headers,
|
|
expect_errors=False
|
|
)
|
|
# management network is not mapped to any interfaces in DB now
|
|
cluster_db = self.db.query(models.Cluster).get(self.cluster['id'])
|
|
objects.Cluster.prepare_for_deployment(cluster_db)
|
|
serializer = get_serializer_for_cluster(cluster_db)
|
|
self.serialized_for_astute = serializer(
|
|
AstuteGraph(cluster_db)).serialize(cluster_db, cluster_db.nodes)
|
|
self.serialized_for_astute = deployment_info_to_legacy(
|
|
self.serialized_for_astute)
|
|
|
|
network_roles = [
|
|
'management',
|
|
'swift/api',
|
|
'neutron/api',
|
|
'sahara/api',
|
|
'ceilometer/api',
|
|
'cinder/api',
|
|
'keystone/api',
|
|
'glance/api',
|
|
'heat/api',
|
|
'nova/api',
|
|
'murano/api',
|
|
'horizon',
|
|
'mgmt/memcache',
|
|
'mgmt/database',
|
|
'mgmt/messaging',
|
|
'neutron/mesh',
|
|
'mgmt/vip',
|
|
'mgmt/corosync',
|
|
'mongo/db',
|
|
'nova/migration'
|
|
]
|
|
for node_data in self.serialized_for_astute:
|
|
for n in node_data['nodes']:
|
|
n_db = objects.Node.get_by_uid(n['uid'])
|
|
if 'controller' in n_db.roles:
|
|
self.assertIn('internal_address', n)
|
|
self.assertIn('internal_netmask', n)
|
|
self.assertIn('public_address', n)
|
|
self.assertIn('public_netmask', n)
|
|
self.assertNotIn('storage_address', n)
|
|
self.assertNotIn('storage_netmask', n)
|
|
else:
|
|
self.assertIn('internal_address', n)
|
|
self.assertIn('internal_netmask', n)
|
|
self.assertNotIn('public_address', n)
|
|
self.assertNotIn('public_netmask', n)
|
|
self.assertIn('storage_address', n)
|
|
self.assertIn('storage_netmask', n)
|
|
nodes = node_data['network_metadata']['nodes']
|
|
for node_name, node_attrs in nodes.items():
|
|
# IPs must be serialized for these roles which are tied to
|
|
# management network
|
|
for role in network_roles:
|
|
self.assertIsNotNone(node_attrs['network_roles'][role])
|
|
|
|
def test_floating_role_belongs_to_public_bridge(self):
|
|
# download default template and assign floating role to public bridge
|
|
net_template = self.env.read_fixtures(['network_template_70'])[0]
|
|
schemes = net_template["adv_net_template"]["default"]["network_scheme"]
|
|
schemes["public"]["roles"]["neutron/floating"] = "br-ex"
|
|
# apply updated template to the cluster
|
|
objects.Cluster.set_network_template(
|
|
self.cluster,
|
|
net_template
|
|
)
|
|
cluster_db = self.db.query(models.Cluster).get(self.cluster['id'])
|
|
nm = objects.Cluster.get_network_manager(self.cluster)
|
|
serializer = self._get_serializer(self.cluster)
|
|
self.serialized_for_astute = serializer.serialize(self.cluster,
|
|
cluster_db.nodes)
|
|
self.serialized_for_astute = self._handle_facts(
|
|
deployment_info_to_legacy(self.serialized_for_astute)
|
|
)
|
|
|
|
for node_data in self.serialized_for_astute:
|
|
node = objects.Node.get_by_uid(node_data['uid'])
|
|
# check nodes with assigned public ip
|
|
if objects.Node.should_have_public_with_ip(node):
|
|
nets = nm.get_node_networks(node)
|
|
ng = nm.get_network_by_netname('public', nets)
|
|
endpoints = node_data["network_scheme"]["endpoints"]
|
|
self.assertEqual(endpoints["br-ex"]["IP"], [ng.get('ip')])
|
|
|
|
def test_get_node_network_mapping(self):
|
|
self.create_more_nodes()
|
|
nm = objects.Cluster.get_network_manager(self.cluster)
|
|
|
|
# according to the template different node roles have different sets of
|
|
# networks (endpoints and network names here)
|
|
node_roles_vs_networks = [
|
|
(['controller'], [('public', 'br-ex'),
|
|
('management', 'br-mgmt'),
|
|
('fuelweb_admin', 'br-fw-admin')]),
|
|
(['compute'], [('private', 'br-prv'),
|
|
('storage', 'br-storage'),
|
|
('management', 'br-mgmt'),
|
|
('fuelweb_admin', 'br-fw-admin')]),
|
|
(['cinder'], [('storage', 'br-storage'),
|
|
('management', 'br-mgmt'),
|
|
('fuelweb_admin', 'br-fw-admin')]),
|
|
(['compute', 'cinder'], [('private', 'br-prv'),
|
|
('storage', 'br-storage'),
|
|
('management', 'br-mgmt'),
|
|
('fuelweb_admin', 'br-fw-admin')]),
|
|
(['controller', 'cinder'], [('public', 'br-ex'),
|
|
('storage', 'br-storage'),
|
|
('management', 'br-mgmt'),
|
|
('fuelweb_admin', 'br-fw-admin')])]
|
|
|
|
for node in self.env.nodes:
|
|
net_names_and_eps = nm.get_node_network_mapping(node)
|
|
for node_roles, networks in node_roles_vs_networks:
|
|
if node.all_roles == set(node_roles):
|
|
self.assertItemsEqual(net_names_and_eps, networks)
|
|
|
|
def test_get_network_name_to_endpoint_mappings(self):
|
|
nm = objects.Cluster.get_network_manager(self.cluster)
|
|
group_id = objects.Cluster.get_default_group(self.cluster).id
|
|
self.assertEqual(
|
|
nm.get_network_name_to_endpoint_mappings(self.cluster),
|
|
{
|
|
group_id: {
|
|
'br-ex': 'public',
|
|
'br-mgmt': 'management',
|
|
'br-fw-admin': 'fuelweb_admin',
|
|
'br-prv': 'private',
|
|
'br-storage': 'storage',
|
|
}
|
|
}
|
|
)
|
|
|
|
def test_assign_ips_in_node_group(self):
|
|
mgmt = self.db.query(models.NetworkGroup).\
|
|
filter_by(name='management').first()
|
|
ips_2_db = self.db.query(models.IPAddr.ip_addr).\
|
|
filter(models.IPAddr.network == mgmt.id,
|
|
models.IPAddr.node.isnot(None))
|
|
# two nodes now
|
|
self.assertEqual(ips_2_db.count(), 2)
|
|
ips_2_str = set(ips_2_db)
|
|
|
|
# add three nodes
|
|
self.create_more_nodes()
|
|
node_ids = set(n.id for n in self.env.nodes)
|
|
ip_ranges = [netaddr.IPRange(r.first, r.last)
|
|
for r in mgmt.ip_ranges]
|
|
nm = objects.Cluster.get_network_manager(self.cluster)
|
|
nm.assign_ips_in_node_group(
|
|
mgmt.id, mgmt.name, node_ids, ip_ranges)
|
|
|
|
ips_5_db = self.db.query(models.IPAddr.ip_addr). \
|
|
filter(models.IPAddr.network == mgmt.id,
|
|
models.IPAddr.node.isnot(None))
|
|
self.assertEqual(ips_5_db.count(), 5)
|
|
ips_5_str = set(ips_5_db)
|
|
# old IPs are the same
|
|
self.assertEqual(len(ips_5_str.difference(ips_2_str)), 3)
|
|
|
|
def check_vendor_specific_is_not_set(self, use_net_template=False):
|
|
node = self.env.create_node(
|
|
cluster_id=self.cluster.id,
|
|
roles=['controller'], primary_tags=['controller']
|
|
)
|
|
objects.Cluster.set_network_template(
|
|
self.cluster,
|
|
self.net_template if use_net_template else None)
|
|
objects.Cluster.prepare_for_deployment(self.cluster)
|
|
serializer = get_serializer_for_cluster(self.cluster)
|
|
net_serializer = serializer.get_net_provider_serializer(self.cluster)
|
|
nm = objects.Cluster.get_network_manager(self.cluster)
|
|
networks = nm.get_node_networks(node)
|
|
endpoints = net_serializer.generate_network_scheme(
|
|
node, networks)['endpoints']
|
|
|
|
for name in endpoints:
|
|
self.assertNotIn('vendor_specific', endpoints[name])
|
|
|
|
def test_vendor_specific_in_deployment_serializer(self):
|
|
self.check_vendor_specific_is_not_set()
|
|
|
|
def test_vendor_specific_in_template_serializer(self):
|
|
self.check_vendor_specific_is_not_set(use_net_template=True)
|
|
|
|
|
|
class TestCustomNetGroupIpAllocation(BaseDeploymentSerializer):
|
|
|
|
env_version = '2015.1.0-7.0'
|
|
|
|
def setUp(self):
|
|
super(TestCustomNetGroupIpAllocation, self).setUp()
|
|
self.cluster = self.create_env()
|
|
self.cluster_db = self.env.clusters[-1]
|
|
|
|
def create_env(self):
|
|
return self.env.create(
|
|
release_kwargs={'version': self.env_version},
|
|
cluster_kwargs={
|
|
'api': False,
|
|
'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
|
|
'net_segment_type': consts.NEUTRON_SEGMENT_TYPES.gre},
|
|
nodes_kwargs=[
|
|
{'roles': ['controller']},
|
|
{'roles': ['compute']},
|
|
])
|
|
|
|
def test_ip_allocation(self):
|
|
self.env._create_network_group(
|
|
cluster=self.cluster, name='test', cidr='172.16.122.0/24',
|
|
meta={'notation': 'ip_ranges',
|
|
'ip_range': ['172.16.122.2', '172.16.122.255']})
|
|
objects.Cluster.prepare_for_deployment(self.cluster_db)
|
|
|
|
ip_column_name = models.IPAddr.ip_addr.label('ip')
|
|
ip_addrs_count = db().query(models.IPAddr).filter(
|
|
"inet '172.16.122/24' >> {0}".format(ip_column_name)
|
|
).count()
|
|
|
|
self.assertEqual(ip_addrs_count, 2)
|
|
|
|
|
|
class TestSerializer70Mixin(object):
|
|
|
|
env_version = "2015.1.0-7.0"
|
|
|
|
|
|
class TestNovaOrchestratorSerializer70(TestSerializer70Mixin,
|
|
TestNovaOrchestratorSerializer,
|
|
PrepareDataMixin):
|
|
|
|
def create_env(self, mode, network_manager='FlatDHCPManager'):
|
|
node_args = [
|
|
{'roles': ['controller', 'cinder'], 'pending_addition': True},
|
|
{'roles': ['compute', 'cinder'], 'pending_addition': True},
|
|
{'roles': ['compute'], 'pending_addition': True},
|
|
{'roles': ['mongo'], 'pending_addition': True},
|
|
{'roles': [], 'pending_roles': ['cinder'],
|
|
'pending_addition': True}]
|
|
|
|
release = self.patch_net_roles_for_release()
|
|
cluster = self.env.create(
|
|
cluster_kwargs={
|
|
'release_id': release.id,
|
|
'mode': mode,
|
|
'net_manager': network_manager,
|
|
'net_provider': consts.CLUSTER_NET_PROVIDERS.nova_network},
|
|
nodes_kwargs=node_args)
|
|
|
|
cluster_db = self.db.query(models.Cluster).get(cluster['id'])
|
|
objects.Cluster.prepare_for_deployment(cluster_db)
|
|
self.db.flush()
|
|
return cluster_db
|
|
|
|
|
|
class TestSerializeInterfaceDriversData70(TestSerializer70Mixin,
|
|
TestSerializeInterfaceDriversData):
|
|
pass
|
|
|
|
|
|
class TestDeploymentHASerializer70(TestSerializer70Mixin,
|
|
TestDeploymentHASerializer61):
|
|
pass
|