545 lines
21 KiB
Python
545 lines
21 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
# Copyright 2013 Mirantis, Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import json
|
|
|
|
from nailgun.api.models import Cluster
|
|
from nailgun.api.models import IPAddrRange
|
|
from nailgun.api.models import Network
|
|
from nailgun.api.models import NetworkGroup
|
|
from nailgun.api.models import Node
|
|
from nailgun.db import db
|
|
from nailgun.orchestrator.deployment_serializers \
|
|
import DeploymentHASerializer
|
|
from nailgun.orchestrator.deployment_serializers \
|
|
import DeploymentMultiSerializer
|
|
from nailgun.settings import settings
|
|
from nailgun.task.helpers import TaskHelper
|
|
from nailgun.test.base import BaseIntegrationTest
|
|
from nailgun.test.base import reverse
|
|
from nailgun.volumes import manager
|
|
|
|
|
|
class OrchestratorSerializerTestBase(BaseIntegrationTest):
|
|
"""Class containts helpers."""
|
|
|
|
def filter_by_role(self, nodes, role):
|
|
return filter(lambda node: node['role'] == role, nodes)
|
|
|
|
def filter_by_uid(self, nodes, uid):
|
|
return filter(lambda node: node['uid'] == uid, nodes)
|
|
|
|
def assert_nodes_with_role(self, nodes, role, count):
|
|
self.assertEquals(len(self.filter_by_role(nodes, role)), count)
|
|
|
|
def get_controllers(self, cluster_id):
|
|
return db().query(Node).\
|
|
filter_by(cluster_id=cluster_id,
|
|
pending_deletion=False).\
|
|
filter(Node.role_list.any(name='controller')).\
|
|
order_by(Node.id)
|
|
|
|
|
|
class TestNovaOrchestratorSerializer(OrchestratorSerializerTestBase):
|
|
|
|
def setUp(self):
|
|
super(TestNovaOrchestratorSerializer, self).setUp()
|
|
self.cluster = self.create_env('multinode')
|
|
|
|
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': [], 'pending_roles': ['cinder'],
|
|
'pending_addition': True}]
|
|
cluster = self.env.create(
|
|
cluster_kwargs={
|
|
'mode': mode,
|
|
'net_manager': network_manager},
|
|
nodes_kwargs=node_args)
|
|
|
|
cluster_db = self.db.query(Cluster).get(cluster['id'])
|
|
TaskHelper.prepare_for_deployment(cluster_db.nodes)
|
|
return cluster_db
|
|
|
|
@property
|
|
def serializer(self):
|
|
return DeploymentMultiSerializer
|
|
|
|
def assert_roles_flattened(self, nodes):
|
|
self.assertEquals(len(nodes), 6)
|
|
self.assert_nodes_with_role(nodes, 'controller', 1)
|
|
self.assert_nodes_with_role(nodes, 'compute', 2)
|
|
self.assert_nodes_with_role(nodes, 'cinder', 3)
|
|
|
|
def test_serialize_nodes(self):
|
|
serialized_nodes = self.serializer.serialize_nodes(self.cluster.nodes)
|
|
self.assert_roles_flattened(serialized_nodes)
|
|
|
|
# Each not should be same as result of
|
|
# serialize_node function
|
|
for serialized_node in serialized_nodes:
|
|
node_db = self.db.query(Node).get(int(serialized_node['uid']))
|
|
|
|
expected_node = self.serializer.serialize_node(
|
|
node_db, serialized_node['role'])
|
|
self.assertEquals(serialized_node, expected_node)
|
|
|
|
def test_serialize_node(self):
|
|
node = self.env.create_node(
|
|
api=True, cluster_id=self.cluster.id, pending_addition=True)
|
|
TaskHelper.prepare_for_deployment(self.cluster.nodes)
|
|
|
|
node_db = self.db.query(Node).get(node['id'])
|
|
serialized_data = self.serializer.serialize_node(node_db, 'controller')
|
|
|
|
self.assertEquals(serialized_data['role'], 'controller')
|
|
self.assertEquals(serialized_data['uid'], str(node_db.id))
|
|
self.assertEquals(serialized_data['status'], node_db.status)
|
|
self.assertEquals(serialized_data['online'], node_db.online)
|
|
self.assertEquals(serialized_data['fqdn'],
|
|
'node-%d.%s' % (node_db.id, settings.DNS_DOMAIN))
|
|
self.assertEquals(
|
|
serialized_data['glance'],
|
|
{'image_cache_max_size': manager.calc_glance_cache_size(
|
|
node_db.attributes.volumes)})
|
|
|
|
def test_node_list(self):
|
|
node_list = self.serializer.get_common_attrs(self.cluster)['nodes']
|
|
|
|
# Check right nodes count with right roles
|
|
self.assert_roles_flattened(node_list)
|
|
|
|
# Check common attrs
|
|
for node in node_list:
|
|
node_db = self.db.query(Node).get(int(node['uid']))
|
|
self.assertEquals(node['public_netmask'], '255.255.255.0')
|
|
self.assertEquals(node['internal_netmask'], '255.255.255.0')
|
|
self.assertEquals(node['storage_netmask'], '255.255.255.0')
|
|
self.assertEquals(node['uid'], str(node_db.id))
|
|
self.assertEquals(node['name'], 'node-%d' % node_db.id)
|
|
self.assertEquals(node['fqdn'], 'node-%d.%s' %
|
|
(node_db.id, settings.DNS_DOMAIN))
|
|
|
|
# Check uncommon attrs
|
|
node_uids = sorted(set([n['uid'] for n in node_list]))
|
|
expected_list = [
|
|
{
|
|
'roles': ['controller', 'cinder'],
|
|
'attrs': {
|
|
'uid': node_uids[0],
|
|
'internal_address': '192.168.0.2',
|
|
'public_address': '172.16.0.2',
|
|
'storage_address': '192.168.1.2'}},
|
|
{
|
|
'roles': ['compute', 'cinder'],
|
|
'attrs': {
|
|
'uid': node_uids[1],
|
|
'internal_address': '192.168.0.3',
|
|
'public_address': '172.16.0.3',
|
|
'storage_address': '192.168.1.3'}},
|
|
{
|
|
'roles': ['compute'],
|
|
'attrs': {
|
|
'uid': node_uids[2],
|
|
'internal_address': '192.168.0.4',
|
|
'public_address': '172.16.0.4',
|
|
'storage_address': '192.168.1.4'}},
|
|
{
|
|
'roles': ['cinder'],
|
|
'attrs': {
|
|
'uid': node_uids[3],
|
|
'internal_address': '192.168.0.5',
|
|
'public_address': '172.16.0.5',
|
|
'storage_address': '192.168.1.5'}}]
|
|
|
|
for expected in expected_list:
|
|
attrs = expected['attrs']
|
|
|
|
for role in expected['roles']:
|
|
nodes = self.filter_by_role(node_list, role)
|
|
node = self.filter_by_uid(nodes, attrs['uid'])[0]
|
|
|
|
self.assertEquals(attrs['internal_address'],
|
|
node['internal_address'])
|
|
self.assertEquals(attrs['public_address'],
|
|
node['public_address'])
|
|
self.assertEquals(attrs['storage_address'],
|
|
node['storage_address'])
|
|
|
|
def test_vlan_manager(self):
|
|
cluster = self.create_env('multinode')
|
|
data = {'net_manager': 'VlanManager'}
|
|
url = reverse('NovaNetworkConfigurationHandler',
|
|
kwargs={'cluster_id': cluster.id})
|
|
self.app.put(url, json.dumps(data),
|
|
headers=self.default_headers,
|
|
expect_errors=False)
|
|
facts = self.serializer.serialize(cluster, cluster.nodes)
|
|
|
|
for fact in facts:
|
|
self.assertEquals(fact['vlan_interface'], 'eth0')
|
|
self.assertEquals(fact['fixed_interface'], 'eth0')
|
|
self.assertEquals(
|
|
fact['novanetwork_parameters']['network_manager'],
|
|
'VlanManager')
|
|
self.assertEquals(
|
|
fact['novanetwork_parameters']['num_networks'], 1)
|
|
self.assertEquals(
|
|
fact['novanetwork_parameters']['vlan_start'], 103)
|
|
self.assertEquals(
|
|
fact['novanetwork_parameters']['network_size'], 256)
|
|
|
|
def test_floatin_ranges_generation(self):
|
|
# Set ip ranges for floating ips
|
|
ranges = [['172.16.0.2', '172.16.0.4'],
|
|
['172.16.0.3', '172.16.0.5'],
|
|
['172.16.0.10', '172.16.0.12']]
|
|
|
|
floating_network_group = self.db.query(NetworkGroup).filter(
|
|
NetworkGroup.name == 'floating'
|
|
).filter(
|
|
NetworkGroup.cluster_id == self.cluster.id).first()
|
|
|
|
# Remove floating ip addr ranges
|
|
self.db.query(IPAddrRange).filter(
|
|
IPAddrRange.network_group_id == floating_network_group.id).delete()
|
|
|
|
# Add new ranges
|
|
for ip_range in ranges:
|
|
new_ip_range = IPAddrRange(
|
|
first=ip_range[0],
|
|
last=ip_range[1],
|
|
network_group_id=floating_network_group.id)
|
|
|
|
self.db.add(new_ip_range)
|
|
self.db.commit()
|
|
facts = self.serializer.serialize(self.cluster, self.cluster.nodes)
|
|
|
|
for fact in facts:
|
|
self.assertEquals(
|
|
fact['floating_network_range'],
|
|
['172.16.0.2-172.16.0.4',
|
|
'172.16.0.3-172.16.0.5',
|
|
'172.16.0.10-172.16.0.12'])
|
|
|
|
def test_configure_interfaces_untagged_network(self):
|
|
for network in self.db.query(Network).all():
|
|
network.vlan_id = None
|
|
self.db.commit()
|
|
node_db = sorted(self.cluster.nodes, key=lambda n: n.id)[0]
|
|
from nailgun.orchestrator.deployment_serializers \
|
|
import NovaNetworkDeploymentSerializer
|
|
interfaces = NovaNetworkDeploymentSerializer.\
|
|
configure_interfaces(node_db)
|
|
|
|
expected_interfaces = {
|
|
'lo': {
|
|
'interface': 'lo',
|
|
'ipaddr': ['127.0.0.1/8']},
|
|
'eth0': {
|
|
'interface': 'eth0',
|
|
'ipaddr': [
|
|
'192.168.0.2/24',
|
|
'172.16.0.2/24',
|
|
'192.168.1.2/24'],
|
|
'gateway': '172.16.0.1'},
|
|
'eth1': {
|
|
'interface': 'eth1',
|
|
'ipaddr': [
|
|
'10.20.0.130/24']}}
|
|
|
|
self.datadiff(expected_interfaces, interfaces)
|
|
|
|
|
|
class TestNovaOrchestratorHASerializer(OrchestratorSerializerTestBase):
|
|
|
|
def setUp(self):
|
|
super(TestNovaOrchestratorHASerializer, self).setUp()
|
|
self.cluster = self.create_env('ha_compact')
|
|
|
|
def create_env(self, mode):
|
|
cluster = self.env.create(
|
|
cluster_kwargs={
|
|
'mode': mode,
|
|
},
|
|
nodes_kwargs=[
|
|
{'roles': ['controller'], 'pending_addition': True},
|
|
{'roles': ['controller'], 'pending_addition': True},
|
|
{'roles': ['controller', 'cinder'], 'pending_addition': True},
|
|
{'roles': ['compute', 'cinder'], 'pending_addition': True},
|
|
{'roles': ['compute'], 'pending_addition': True},
|
|
{'roles': ['cinder'], 'pending_addition': True}])
|
|
|
|
cluster_db = self.db.query(Cluster).get(cluster['id'])
|
|
TaskHelper.prepare_for_deployment(cluster_db.nodes)
|
|
return cluster_db
|
|
|
|
@property
|
|
def serializer(self):
|
|
return DeploymentHASerializer
|
|
|
|
def test_set_deployment_priorities(self):
|
|
nodes = [
|
|
{'role': 'primary-swift-proxy'},
|
|
{'role': 'swift-proxy'},
|
|
{'role': 'storage'},
|
|
{'role': 'primary-controller'},
|
|
{'role': 'controller'},
|
|
{'role': 'controller'},
|
|
{'role': 'ceph-osd'},
|
|
{'role': 'other'}
|
|
]
|
|
self.serializer.set_deployment_priorities(nodes)
|
|
expected_priorities = [
|
|
{'role': 'primary-swift-proxy', 'priority': 100},
|
|
{'role': 'swift-proxy', 'priority': 200},
|
|
{'role': 'storage', 'priority': 300},
|
|
{'role': 'primary-controller', 'priority': 400},
|
|
{'role': 'controller', 'priority': 500},
|
|
{'role': 'controller', 'priority': 600},
|
|
{'role': 'ceph-osd', 'priority': 700},
|
|
{'role': 'other', 'priority': 700}
|
|
]
|
|
self.assertEquals(expected_priorities, nodes)
|
|
|
|
def test_node_list(self):
|
|
serialized_nodes = self.serializer.node_list(self.cluster.nodes)
|
|
|
|
for node in serialized_nodes:
|
|
# Each node has swift_zone
|
|
self.assertEquals(node['swift_zone'], node['uid'])
|
|
|
|
def test_get_common_attrs(self):
|
|
attrs = self.serializer.get_common_attrs(self.cluster)
|
|
# vips
|
|
self.assertEquals(attrs['management_vip'], '192.168.0.8')
|
|
self.assertEquals(attrs['public_vip'], '172.16.0.8')
|
|
|
|
# last_contrller
|
|
controllers = self.get_controllers(self.cluster.id)
|
|
self.assertEquals(attrs['last_controller'],
|
|
'node-%d' % controllers[-1].id)
|
|
|
|
# primary_controller
|
|
controllers = self.filter_by_role(attrs['nodes'], 'primary-controller')
|
|
self.assertEquals(controllers[0]['role'], 'primary-controller')
|
|
|
|
# mountpoints and mp attrs
|
|
self.assertEquals(
|
|
attrs['mp'],
|
|
[{'point': '1', 'weight': '1'},
|
|
{'point': '2', 'weight': '2'}])
|
|
|
|
|
|
class TestNeutronOrchestratorSerializer(OrchestratorSerializerTestBase):
|
|
|
|
def setUp(self):
|
|
super(TestNeutronOrchestratorSerializer, self).setUp()
|
|
self.cluster = self.create_env('multinode')
|
|
|
|
def create_env(self, mode, segment_type='vlan'):
|
|
cluster = self.env.create(
|
|
cluster_kwargs={
|
|
'mode': mode,
|
|
'net_provider': 'neutron',
|
|
'net_segment_type': segment_type
|
|
},
|
|
nodes_kwargs=[
|
|
{'roles': ['controller', 'cinder'], 'pending_addition': True},
|
|
{'roles': ['compute', 'cinder'], 'pending_addition': True},
|
|
{'roles': ['compute'], 'pending_addition': True},
|
|
{'roles': [], 'pending_roles': ['cinder'],
|
|
'pending_addition': True}])
|
|
|
|
cluster_db = self.db.query(Cluster).get(cluster['id'])
|
|
TaskHelper.prepare_for_deployment(cluster_db.nodes)
|
|
return cluster_db
|
|
|
|
@property
|
|
def serializer(self):
|
|
return DeploymentMultiSerializer
|
|
|
|
def assert_roles_flattened(self, nodes):
|
|
self.assertEquals(len(nodes), 6)
|
|
self.assert_nodes_with_role(nodes, 'controller', 1)
|
|
self.assert_nodes_with_role(nodes, 'compute', 2)
|
|
self.assert_nodes_with_role(nodes, 'cinder', 3)
|
|
|
|
def test_serialize_nodes(self):
|
|
serialized_nodes = self.serializer.serialize_nodes(self.cluster.nodes)
|
|
self.assert_roles_flattened(serialized_nodes)
|
|
|
|
# Each not should be same as result of
|
|
# serialize_node function
|
|
for serialized_node in serialized_nodes:
|
|
node_db = self.db.query(Node).get(int(serialized_node['uid']))
|
|
|
|
expected_node = self.serializer.serialize_node(
|
|
node_db, serialized_node['role'])
|
|
self.assertEquals(serialized_node, expected_node)
|
|
|
|
def test_serialize_node(self):
|
|
node = self.env.create_node(
|
|
api=True, cluster_id=self.cluster.id, pending_addition=True)
|
|
TaskHelper.prepare_for_deployment(self.cluster.nodes)
|
|
|
|
node_db = self.db.query(Node).get(node['id'])
|
|
serialized_data = self.serializer.serialize_node(node_db, 'controller')
|
|
|
|
self.assertEquals(serialized_data['role'], 'controller')
|
|
self.assertEquals(serialized_data['uid'], str(node_db.id))
|
|
self.assertEquals(serialized_data['status'], node_db.status)
|
|
self.assertEquals(serialized_data['online'], node_db.online)
|
|
self.assertEquals(serialized_data['fqdn'],
|
|
'node-%d.%s' % (node_db.id, settings.DNS_DOMAIN))
|
|
|
|
def test_node_list(self):
|
|
node_list = self.serializer.get_common_attrs(self.cluster)['nodes']
|
|
|
|
# Check right nodes count with right roles
|
|
self.assert_roles_flattened(node_list)
|
|
|
|
# Check common attrs
|
|
for node in node_list:
|
|
node_db = self.db.query(Node).get(int(node['uid']))
|
|
self.assertEquals(node['public_netmask'], '255.255.255.0')
|
|
self.assertEquals(node['internal_netmask'], '255.255.255.0')
|
|
self.assertEquals(node['storage_netmask'], '255.255.255.0')
|
|
self.assertEquals(node['uid'], str(node_db.id))
|
|
self.assertEquals(node['name'], 'node-%d' % node_db.id)
|
|
self.assertEquals(node['fqdn'], 'node-%d.%s' %
|
|
(node_db.id, settings.DNS_DOMAIN))
|
|
|
|
# Check uncommon attrs
|
|
node_uids = sorted(set([n['uid'] for n in node_list]))
|
|
expected_list = [
|
|
{
|
|
'roles': ['controller', 'cinder'],
|
|
'attrs': {
|
|
'uid': node_uids[0],
|
|
'internal_address': '192.168.0.2',
|
|
'public_address': '172.16.0.2',
|
|
'storage_address': '192.168.1.2'}},
|
|
{
|
|
'roles': ['compute', 'cinder'],
|
|
'attrs': {
|
|
'uid': node_uids[1],
|
|
'internal_address': '192.168.0.3',
|
|
'public_address': '172.16.0.3',
|
|
'storage_address': '192.168.1.3'}},
|
|
{
|
|
'roles': ['compute'],
|
|
'attrs': {
|
|
'uid': node_uids[2],
|
|
'internal_address': '192.168.0.4',
|
|
'public_address': '172.16.0.4',
|
|
'storage_address': '192.168.1.4'}},
|
|
{
|
|
'roles': ['cinder'],
|
|
'attrs': {
|
|
'uid': node_uids[3],
|
|
'internal_address': '192.168.0.5',
|
|
'public_address': '172.16.0.5',
|
|
'storage_address': '192.168.1.5'}}]
|
|
|
|
for expected in expected_list:
|
|
attrs = expected['attrs']
|
|
|
|
for role in expected['roles']:
|
|
nodes = self.filter_by_role(node_list, role)
|
|
node = self.filter_by_uid(nodes, attrs['uid'])[0]
|
|
|
|
self.assertEquals(attrs['internal_address'],
|
|
node['internal_address'])
|
|
self.assertEquals(attrs['public_address'],
|
|
node['public_address'])
|
|
self.assertEquals(attrs['storage_address'],
|
|
node['storage_address'])
|
|
|
|
def test_gre_segmentation(self):
|
|
cluster = self.create_env('multinode', 'gre')
|
|
facts = self.serializer.serialize(cluster, cluster.nodes)
|
|
|
|
for fact in facts:
|
|
self.assertEquals(
|
|
fact['quantum_settings']['L2']['segmentation_type'], 'gre')
|
|
self.assertEquals(
|
|
'br-prv' in fact['network_scheme']['endpoints'], False)
|
|
self.assertEquals(
|
|
'private' in (fact['network_scheme']['roles']), False)
|
|
|
|
|
|
class TestNeutronOrchestratorHASerializer(OrchestratorSerializerTestBase):
|
|
|
|
def setUp(self):
|
|
super(TestNeutronOrchestratorHASerializer, self).setUp()
|
|
self.cluster = self.create_env('ha_compact')
|
|
|
|
def create_env(self, mode):
|
|
cluster = self.env.create(
|
|
cluster_kwargs={
|
|
'mode': mode,
|
|
'net_provider': 'neutron',
|
|
'net_segment_type': 'vlan'
|
|
},
|
|
nodes_kwargs=[
|
|
{'roles': ['controller'], 'pending_addition': True},
|
|
{'roles': ['controller'], 'pending_addition': True},
|
|
{'roles': ['controller', 'cinder'], 'pending_addition': True},
|
|
{'roles': ['compute', 'cinder'], 'pending_addition': True},
|
|
{'roles': ['compute'], 'pending_addition': True},
|
|
{'roles': ['cinder'], 'pending_addition': True}
|
|
]
|
|
)
|
|
|
|
cluster_db = self.db.query(Cluster).get(cluster['id'])
|
|
TaskHelper.prepare_for_deployment(cluster_db.nodes)
|
|
return cluster_db
|
|
|
|
@property
|
|
def serializer(self):
|
|
return DeploymentHASerializer
|
|
|
|
def test_node_list(self):
|
|
serialized_nodes = self.serializer.node_list(self.cluster.nodes)
|
|
|
|
for node in serialized_nodes:
|
|
# Each node has swift_zone
|
|
self.assertEquals(node['swift_zone'], node['uid'])
|
|
|
|
def test_get_common_attrs(self):
|
|
attrs = self.serializer.get_common_attrs(self.cluster)
|
|
# vips
|
|
self.assertEquals(attrs['management_vip'], '192.168.0.8')
|
|
self.assertEquals(attrs['public_vip'], '172.16.0.8')
|
|
|
|
# last_contrller
|
|
controllers = self.get_controllers(self.cluster.id)
|
|
self.assertEquals(attrs['last_controller'],
|
|
'node-%d' % controllers[-1].id)
|
|
|
|
# primary_controller
|
|
controllers = self.filter_by_role(attrs['nodes'], 'primary-controller')
|
|
self.assertEquals(controllers[0]['role'], 'primary-controller')
|
|
|
|
# mountpoints and mp attrs
|
|
self.assertEquals(
|
|
attrs['mp'],
|
|
[{'point': '1', 'weight': '1'},
|
|
{'point': '2', 'weight': '2'}])
|