Fix working sahara with heat and nova-network

Uses OS::Nova::FloatingIP and OS::Nova::FloatingIPAssociation
heat resources for assignment floating ip

Added two unit tests:
* for nova-network with autoassignment floating ip
* for nova-network without autoassignment floating ip

Change-Id: I82a28759bc13992d765969ef8143bd364dc7cf2d
Closes-bug: #1259176
This commit is contained in:
Sergey Reshetnyak 2014-05-13 18:02:10 +04:00
parent 0baeb0ee5a
commit 727a59e512
5 changed files with 261 additions and 24 deletions

View File

@ -0,0 +1,13 @@
"%(floating_ip_name)s": {
"Type": "OS::Nova::FloatingIP",
"Properties": {
"pool": "%(pool)s"
}
},
"%(floating_ip_assoc_name)s": {
"Type": "OS::Nova::FloatingIPAssociation",
"Properties": {
"floating_ip": { "Ref" : "%(floating_ip_name)s" },
"server_id": { "Ref" : "%(instance_name)s" }
}
}

View File

@ -0,0 +1,63 @@
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Hadoop Cluster by Sahara",
"Resources" : {
"cluster-worker-001" : {
"Type" : "OS::Nova::Server",
"Properties" : {
"name" : "cluster-worker-001",
"flavor" : "42",
"image" : "1",
"key_name" : "user_key",
"user_data": {
"Fn::Join" : ["\n", ["line2", "line3"]]
}
}
},
"cluster-worker-001-volume-0" : {
"Type" : "OS::Cinder::Volume",
"Properties" : {
"name" : "cluster-worker-001-volume-0",
"size" : "10"
}
},
"cluster-worker-001-volume-attachment-0" : {
"Type" : "OS::Cinder::VolumeAttachment",
"Properties" : {
"instance_uuid" : { "Ref" : "cluster-worker-001" },
"volume_id" : { "Ref" : "cluster-worker-001-volume-0" },
"mountpoint" : null
}
},
"cluster-worker-001-volume-1" : {
"Type" : "OS::Cinder::Volume",
"Properties" : {
"name" : "cluster-worker-001-volume-1",
"size" : "10"
}
},
"cluster-worker-001-volume-attachment-1" : {
"Type" : "OS::Cinder::VolumeAttachment",
"Properties" : {
"instance_uuid" : { "Ref" : "cluster-worker-001" },
"volume_id" : { "Ref" : "cluster-worker-001-volume-1" },
"mountpoint" : null
}
},
"cluster-master-001" : {
"Type" : "OS::Nova::Server",
"Properties" : {
"name" : "cluster-master-001",
"flavor" : "42",
"image" : "1",
"key_name" : "user_key",
"user_data": {
"Fn::Join" : ["\n", ["line1", "line2"]]
}
}
}
},
"Outputs" : {}
}

View File

@ -0,0 +1,89 @@
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Hadoop Cluster by Sahara",
"Resources" : {
"cluster-worker-001-floating-assoc" : {
"Type" : "OS::Nova::FloatingIPAssociation",
"Properties" : {
"floating_ip" : { "Ref" : "cluster-worker-001-floating" },
"server_id" : { "Ref" : "cluster-worker-001" }
}
},
"cluster-worker-001-floating" : {
"Type" : "OS::Nova::FloatingIP",
"Properties" : {
"pool" : "floating"
}
},
"cluster-worker-001" : {
"Type" : "OS::Nova::Server",
"Properties" : {
"name" : "cluster-worker-001",
"flavor" : "42",
"image" : "1",
"key_name" : "user_key",
"user_data": {
"Fn::Join" : ["\n", ["line2", "line3"]]
}
}
},
"cluster-worker-001-volume-0" : {
"Type" : "OS::Cinder::Volume",
"Properties" : {
"name" : "cluster-worker-001-volume-0",
"size" : "10"
}
},
"cluster-worker-001-volume-attachment-0" : {
"Type" : "OS::Cinder::VolumeAttachment",
"Properties" : {
"instance_uuid" : { "Ref" : "cluster-worker-001" },
"volume_id" : { "Ref" : "cluster-worker-001-volume-0" },
"mountpoint" : null
}
},
"cluster-worker-001-volume-1" : {
"Type" : "OS::Cinder::Volume",
"Properties" : {
"name" : "cluster-worker-001-volume-1",
"size" : "10"
}
},
"cluster-worker-001-volume-attachment-1" : {
"Type" : "OS::Cinder::VolumeAttachment",
"Properties" : {
"instance_uuid" : { "Ref" : "cluster-worker-001" },
"volume_id" : { "Ref" : "cluster-worker-001-volume-1" },
"mountpoint" : null
}
},
"cluster-master-001-floating-assoc" : {
"Type" : "OS::Nova::FloatingIPAssociation",
"Properties" : {
"floating_ip" : { "Ref" : "cluster-master-001-floating" },
"server_id" : { "Ref" : "cluster-master-001" }
}
},
"cluster-master-001-floating" : {
"Type" : "OS::Nova::FloatingIP",
"Properties" : {
"pool" : "floating"
}
},
"cluster-master-001" : {
"Type" : "OS::Nova::Server",
"Properties" : {
"name" : "cluster-master-001",
"flavor" : "42",
"image" : "1",
"key_name" : "user_key",
"user_data": {
"Fn::Join" : ["\n", ["line1", "line2"]]
}
}
}
},
"Outputs" : {}
}

View File

@ -34,6 +34,8 @@ class TestHeat(unittest2.TestCase):
"cluster-worker-001-port")
self.assertEqual(h._get_floating_name(inst_name),
"cluster-worker-001-floating")
self.assertEqual(h._get_floating_assoc_name(inst_name),
"cluster-worker-001-floating-assoc")
self.assertEqual(h._get_volume_name(inst_name, 1),
"cluster-worker-001-volume-1")
self.assertEqual(h._get_volume_attach_name(inst_name, 1),
@ -73,30 +75,40 @@ class TestClusterTemplate(base.SaharaWithDbTestCase):
into Heat templates.
"""
def _make_node_groups(self, floating_ip_pool=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)
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)
return ng1, ng2
def _make_cluster(self, mng_network, ng1, ng2):
return tu.create_cluster("cluster", "tenant1", "general",
"1.2.1", [ng1, ng2],
user_keypair_id='user_key',
neutron_management_network=mng_network,
default_image_id='1', anti_affinity=[],
image_id=None)
def _make_heat_template(self, cluster, ng1, ng2):
heat_template = h.ClusterTemplate(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_load_template_use_neutron(self):
"""This test checks Heat cluster template with Neutron enabled.
Two NodeGroups used: 'master' with Ephemeral drive attached and
'worker' with 2 attached volumes 10GB size each
"""
ng1 = tu.make_ng_dict('master', 42, ['namenode'], 1,
floating_ip_pool='floating', image_id=None,
volumes_per_node=0, volumes_size=0, id=1)
ng2 = tu.make_ng_dict('worker', 42, ['datanode'], 1,
floating_ip_pool='floating', image_id=None,
volumes_per_node=2, volumes_size=10, id=2)
cluster = tu.create_cluster("cluster", "tenant1", "general",
"1.2.1", [ng1, ng2],
user_keypair_id='user_key',
neutron_management_network='private_net',
default_image_id='1', anti_affinity=[],
image_id=None)
heat_template = h.ClusterTemplate(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'))
ng1, ng2 = self._make_node_groups('floating')
cluster = self._make_cluster('private_net', ng1, ng2)
heat_template = self._make_heat_template(cluster, ng1, ng2)
self.override_config("use_neutron", True)
main_template = h._load_template(
'main.heat', {'resources':
@ -108,6 +120,50 @@ class TestClusterTemplate(base.SaharaWithDbTestCase):
"tests/unit/resources/"
"test_serialize_resources_use_neutron.heat")))
def test_load_template_use_nova_network_without_autoassignment(self):
"""This test checks Heat cluster template with Nova Network enabled
without autoassignment floating ip.
Two NodeGroups used: 'master' with Ephemeral drive attached and
'worker' with 2 attached volumes 10GB size each
"""
ng1, ng2 = self._make_node_groups('floating')
cluster = self._make_cluster(None, ng1, ng2)
heat_template = self._make_heat_template(cluster, ng1, ng2)
self.override_config("use_neutron", False)
main_template = h._load_template(
'main.heat', {'resources':
heat_template._serialize_resources()})
self.assertEqual(
json.loads(main_template),
json.loads(f.get_file_text(
"tests/unit/resources/"
"test_serialize_resources_use_nn_without_autoassignment.heat"))
)
def test_load_template_use_nova_network_with_autoassignment(self):
"""This test checks Heat cluster template with Nova Network enabled
with autoassignment floating ip.
Two NodeGroups used: 'master' with Ephemeral drive attached and
'worker' with 2 attached volumes 10GB size each
"""
ng1, ng2 = self._make_node_groups()
cluster = self._make_cluster(None, ng1, ng2)
heat_template = self._make_heat_template(cluster, ng1, ng2)
self.override_config("use_neutron", False)
main_template = h._load_template(
'main.heat', {'resources':
heat_template._serialize_resources()})
self.assertEqual(
json.loads(main_template),
json.loads(f.get_file_text(
"tests/unit/resources/"
"test_serialize_resources_use_nn_with_autoassignment.heat"))
)
def test_load_template_with_anti_affinity_single_ng(self):
"""This test checks Heat cluster template with Neutron enabled
and anti-affinity feature enabled for single node process

View File

@ -47,6 +47,10 @@ def _get_floating_name(inst_name):
return '%s-floating' % inst_name
def _get_floating_assoc_name(inst_name):
return '%s-floating-assoc' % inst_name
def _get_volume_name(inst_name, volume_idx):
return '%s-volume-%i' % (inst_name, volume_idx)
@ -132,9 +136,6 @@ class ClusterTemplate(object):
def _serialize_instance(self, ng, idx, aa_groups):
inst_name = _get_inst_name(self.cluster.name, ng.name, idx)
# TODO(dmitryme): support floating IPs for nova-network without
# auto-assignment
nets = ''
if CONF.use_neutron:
port_name = _get_port_name(inst_name)
@ -144,8 +145,12 @@ class ClusterTemplate(object):
nets = '"networks" : [{ "port" : { "Ref" : "%s" }}],' % port_name
if ng.floating_ip_pool:
yield self._serialize_floating(inst_name, port_name,
ng.floating_ip_pool)
yield self._serialize_neutron_floating(inst_name, port_name,
ng.floating_ip_pool)
else:
if ng.floating_ip_pool:
yield self._serialize_nova_floating(inst_name,
ng.floating_ip_pool)
aa_names = []
for node_process in ng.node_processes:
@ -185,13 +190,24 @@ class ClusterTemplate(object):
return _load_template('neutron-port.heat', fields)
def _serialize_floating(self, inst_name, port_name, floating_net_id):
def _serialize_neutron_floating(self, inst_name, port_name,
floating_net_id):
fields = {'floating_ip_name': _get_floating_name(inst_name),
'floating_net_id': floating_net_id,
'port_name': port_name}
return _load_template('neutron-floating.heat', fields)
def _serialize_nova_floating(self, inst_name, floating_pool_name):
fields = {
'floating_ip_name': _get_floating_name(inst_name),
'floating_ip_assoc_name': _get_floating_assoc_name(inst_name),
'instance_name': inst_name,
'pool': floating_pool_name
}
return _load_template('nova-floating.heat', fields)
def _serialize_volume(self, inst_name, volume_idx, volumes_size):
fields = {'volume_name': _get_volume_name(inst_name, volume_idx),
'volumes_size': volumes_size,