168 lines
7.1 KiB
Python
168 lines
7.1 KiB
Python
# Copyright (c) 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 mock
|
|
|
|
from sahara.conductor import resource as r
|
|
from sahara.service.heat import templates as h
|
|
from sahara.tests.unit import base
|
|
from sahara.tests.unit import testutils as tu
|
|
|
|
|
|
class TestClusterTemplate(base.SaharaWithDbTestCase):
|
|
"""Checks valid structure of Resources section in generated Heat templates.
|
|
|
|
1. It checks templates generation with different OpenStack
|
|
network installations: Neutron, NovaNetwork with floating Ip auto
|
|
assignment set to True or False.
|
|
2. Cinder volume attachments.
|
|
3. Basic instances creations with multi line user data provided.
|
|
4. Anti-affinity feature with proper nova scheduler hints included
|
|
into Heat templates.
|
|
"""
|
|
|
|
def _make_node_groups(self, floating_ip_pool=None, volume_type=None):
|
|
ng1 = tu.make_ng_dict('master', 42, ['namenode'], 1,
|
|
floating_ip_pool=floating_ip_pool, image_id=None,
|
|
volumes_per_node=0, volumes_size=0, id="1",
|
|
image_username='root', volume_type=None)
|
|
ng2 = tu.make_ng_dict('worker', 42, ['datanode'], 1,
|
|
floating_ip_pool=floating_ip_pool, image_id=None,
|
|
volumes_per_node=2, volumes_size=10, id="2",
|
|
image_username='root', volume_type=volume_type)
|
|
return ng1, ng2
|
|
|
|
def _make_cluster(self, mng_network, ng1, ng2, anti_affinity=[]):
|
|
return tu.create_cluster("cluster", "tenant1", "general",
|
|
"2.6.0", [ng1, ng2],
|
|
user_keypair_id='user_key',
|
|
neutron_management_network=mng_network,
|
|
default_image_id='1', image_id=None,
|
|
anti_affinity=anti_affinity)
|
|
|
|
def _make_heat_template(self, cluster, ng1, ng2):
|
|
heat_template = h.ClusterStack(cluster)
|
|
heat_template.add_node_group_extra(ng1['id'], 1,
|
|
get_ud_generator('line1\nline2'))
|
|
heat_template.add_node_group_extra(ng2['id'], 1,
|
|
get_ud_generator('line2\nline3'))
|
|
return heat_template
|
|
|
|
def test_get_anti_affinity_scheduler_hints(self):
|
|
ng1, ng2 = self._make_node_groups('floating')
|
|
cluster = self._make_cluster('private_net', ng1, ng2,
|
|
anti_affinity=["datanode"])
|
|
heat_template = self._make_heat_template(cluster, ng1, ng2)
|
|
|
|
ng1 = [ng for ng in cluster.node_groups if ng.name == "master"][0]
|
|
ng2 = [ng for ng in cluster.node_groups if ng.name == "worker"][0]
|
|
|
|
expected = {"scheduler_hints": {"group": {"Ref": "cluster-aa-group"}}}
|
|
actual = heat_template._get_anti_affinity_scheduler_hints(ng2)
|
|
self.assertEqual(expected, actual)
|
|
|
|
expected = {}
|
|
actual = heat_template._get_anti_affinity_scheduler_hints(ng1)
|
|
self.assertEqual(expected, actual)
|
|
|
|
def test_get_security_groups(self):
|
|
ng1, ng2 = self._make_node_groups('floating')
|
|
ng1['security_groups'] = ['1', '2']
|
|
ng2['security_groups'] = ['3', '4']
|
|
ng2['auto_security_group'] = True
|
|
cluster = self._make_cluster('private_net', ng1, ng2)
|
|
heat_template = self._make_heat_template(cluster, ng1, ng2)
|
|
|
|
ng1 = [ng for ng in cluster.node_groups if ng.name == "master"][0]
|
|
ng2 = [ng for ng in cluster.node_groups if ng.name == "worker"][0]
|
|
expected = ['1', '2']
|
|
actual = heat_template._get_security_groups(ng1)
|
|
self.assertEqual(expected, actual)
|
|
|
|
expected = ['3', '4', {'Ref': 'cluster-worker-2'}]
|
|
actual = heat_template._get_security_groups(ng2)
|
|
self.assertEqual(expected, actual)
|
|
|
|
def _generate_auto_security_group_template(self, use_neutron):
|
|
self.override_config('use_neutron', use_neutron)
|
|
ng1, ng2 = self._make_node_groups('floating')
|
|
cluster = self._make_cluster('private_net', ng1, ng2)
|
|
ng1['cluster'] = cluster
|
|
ng2['cluster'] = cluster
|
|
ng1 = r.NodeGroupResource(ng1)
|
|
ng2 = r.NodeGroupResource(ng2)
|
|
heat_template = self._make_heat_template(cluster, ng1, ng2)
|
|
return heat_template._serialize_auto_security_group(ng1)
|
|
|
|
@mock.patch('sahara.utils.openstack.neutron.get_private_network_cidrs')
|
|
def test_serialize_auto_security_group_neutron(self, patched):
|
|
ipv4_cidr = '192.168.0.0/24'
|
|
ipv6_cidr = 'fe80::/64'
|
|
patched.side_effect = lambda cluster: [ipv4_cidr, ipv6_cidr]
|
|
expected_rules = [
|
|
('0.0.0.0/0', 'IPv4', 'tcp', '22', '22'),
|
|
('::/0', 'IPv6', 'tcp', '22', '22'),
|
|
(ipv4_cidr, 'IPv4', 'tcp', '1', '65535'),
|
|
(ipv4_cidr, 'IPv4', 'udp', '1', '65535'),
|
|
(ipv4_cidr, 'IPv4', 'icmp', '0', '255'),
|
|
(ipv6_cidr, 'IPv6', 'tcp', '1', '65535'),
|
|
(ipv6_cidr, 'IPv6', 'udp', '1', '65535'),
|
|
(ipv6_cidr, 'IPv6', 'icmp', '0', '255'),
|
|
]
|
|
expected = {'cluster-master-1': {
|
|
'type': 'OS::Neutron::SecurityGroup',
|
|
'properties': {
|
|
'description': 'Auto security group created by Sahara '
|
|
'for Node Group \'master\' of cluster \'cluster\'.',
|
|
'rules': [{
|
|
'remote_ip_prefix': rule[0],
|
|
'ethertype': rule[1],
|
|
'protocol': rule[2],
|
|
'port_range_min': rule[3],
|
|
'port_range_max': rule[4]
|
|
} for rule in expected_rules]
|
|
}
|
|
}}
|
|
actual = self._generate_auto_security_group_template(True)
|
|
self.assertEqual(expected, actual)
|
|
|
|
def test_serialize_auto_security_group_nova_network(self):
|
|
expected = {'cluster-master-1': {
|
|
'type': 'AWS::EC2::SecurityGroup',
|
|
'properties': {
|
|
'GroupDescription': 'Auto security group created by Sahara'
|
|
' for Node Group \'master\' of cluster \'cluster\'.',
|
|
'SecurityGroupIngress': [{
|
|
'ToPort': '22',
|
|
'CidrIp': '0.0.0.0/0',
|
|
'FromPort': '22',
|
|
'IpProtocol': 'tcp'
|
|
}, {
|
|
'ToPort': '22',
|
|
'CidrIp': '::/0',
|
|
'FromPort': '22',
|
|
'IpProtocol': 'tcp'
|
|
}]
|
|
}
|
|
}}
|
|
actual = self._generate_auto_security_group_template(False)
|
|
self.assertEqual(expected, actual)
|
|
|
|
|
|
def get_ud_generator(s):
|
|
def generator(*args, **kwargs):
|
|
return s
|
|
return generator
|