From 10716b8f1beb11b5acce8f35fad94b943d330eaa Mon Sep 17 00:00:00 2001 From: Denis Makogon Date: Fri, 30 May 2014 17:40:21 +0300 Subject: [PATCH] Use tcp/udp ports from config for heat templates Reasons: - Trove should use tcp/upd ports from config for rendering heat templates. Changes: - adding another two rendering parameter: - tcp_rules; - udp_rules; - adding validation for empty rules sets: - if no tcp/udp ports were mentioned - no rules will be assigned AWS::EC2::SecurityGroup. Change-Id: I066aab0e7a32136608e2a6e23999e85bc637debd Partial-Bug: #1276228 --- trove/taskmanager/models.py | 18 ++++++++++- trove/templates/cassandra/heat.template | 22 +++++++++---- trove/templates/mongodb/heat.template | 22 +++++++++---- trove/templates/mysql/heat.template | 22 +++++++++---- trove/templates/redis/heat.template | 22 +++++++++---- trove/tests/unittests/common/test_template.py | 31 +++++++++++++++++++ 6 files changed, 112 insertions(+), 25 deletions(-) diff --git a/trove/taskmanager/models.py b/trove/taskmanager/models.py index 31fbcfc561..4e81fdb4f5 100644 --- a/trove/taskmanager/models.py +++ b/trove/taskmanager/models.py @@ -369,18 +369,34 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin): LOG.debug("end _create_server_volume for id: %s" % self.id) return volume_info + def _build_sg_rules_mapping(self, rule_ports): + final = [] + cidr = CONF.trove_security_group_rule_cidr + for port_or_range in set(rule_ports): + from_, to_ = utils.gen_ports(port_or_range) + final.append({'cidr': cidr, + 'from_': str(from_), + 'to_': str(to_)}) + return final + def _create_server_volume_heat(self, flavor, image_id, datastore_manager, volume_size, availability_zone, nics): LOG.debug("begin _create_server_volume_heat for id: %s" % self.id) try: client = create_heat_client(self.context) + tcp_rules_mapping_list = self._build_sg_rules_mapping(CONF.get( + datastore_manager).tcp_ports) + udp_ports_mapping_list = self._build_sg_rules_mapping(CONF.get( + datastore_manager).udp_ports) ifaces, ports = self._build_heat_nics(nics) template_obj = template.load_heat_template(datastore_manager) heat_template_unicode = template_obj.render( volume_support=CONF.trove_volume_support, - ifaces=ifaces, ports=ports) + ifaces=ifaces, ports=ports, + tcp_rules=tcp_rules_mapping_list, + udp_rules=udp_ports_mapping_list) try: heat_template = heat_template_unicode.encode('utf-8') except UnicodeEncodeError: diff --git a/trove/templates/cassandra/heat.template b/trove/templates/cassandra/heat.template index b74b438dea..7d01f59e2d 100644 --- a/trove/templates/cassandra/heat.template +++ b/trove/templates/cassandra/heat.template @@ -23,7 +23,7 @@ Resources: Type: OS::Neutron::Port Properties: network_id: "{{ port.net_id }}" - security_groups: [{Ref: CassandraDbaasSG}] + security_groups: [{Ref: DatastoreSG}] {% if port.fixed_ip %} fixed_ips: [{"ip_address": "{{ port.fixed_ip }}"}] {% endif %} @@ -48,7 +48,7 @@ Resources: ImageId: {Ref: ImageId} InstanceType: {Ref: Flavor} AvailabilityZone: {Ref: AvailabilityZone} - SecurityGroups : [{Ref: CassandraDbaasSG}] + SecurityGroups : [{Ref: DatastoreSG}] UserData: Fn::Base64: Fn::Join: @@ -71,15 +71,25 @@ Resources: VolumeId: {Ref: DataVolume} Device: /dev/vdb {% endif %} - CassandraDbaasSG: + DatastoreSG: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Default Security group for Cassandra +{% if tcp_rules or udp_rules %} SecurityGroupIngress: +{% for rule in tcp_rules %} - IpProtocol: "tcp" - FromPort: "9160" - ToPort: "9160" - CidrIp: "0.0.0.0/0" + FromPort: "{{rule.from_}}" + ToPort: "{{rule.to_}}" + CidrIp: "{{rule.cidr}}" +{% endfor %} +{% for rule in udp_rules %} + - IpProtocol: "udp" + FromPort: "{{rule.from_}}" + ToPort: "{{rule.to_}}" + CidrIp: "{{rule.cidr}}" +{% endfor %} +{% endif %} DatabaseIPAddress: Type: AWS::EC2::EIP DatabaseIPAssoc : diff --git a/trove/templates/mongodb/heat.template b/trove/templates/mongodb/heat.template index 91a0f49c91..d8fd4b7042 100644 --- a/trove/templates/mongodb/heat.template +++ b/trove/templates/mongodb/heat.template @@ -23,7 +23,7 @@ Resources: Type: OS::Neutron::Port Properties: network_id: "{{ port.net_id }}" - security_groups: [{Ref: DBaaSSG}] + security_groups: [{Ref: DatastoreSG}] {% if port.fixed_ip %} fixed_ips: [{"ip_address": "{{ port.fixed_ip }}"}] {% endif %} @@ -51,7 +51,7 @@ Resources: {% if ifaces %} NetworkInterfaces: [{{ ifaces|join(', ') }}] {% else %} - SecurityGroups: [{Ref: DBaaSSG}] + SecurityGroups: [{Ref: DatastoreSG}] {% endif %} UserData: Fn::Base64: @@ -75,15 +75,25 @@ Resources: VolumeId: {Ref: DataVolume} Device: /dev/vdb {% endif %} - DBaaSSG: + DatastoreSG: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Default Security group for MongoDB +{% if tcp_rules or udp_rules %} SecurityGroupIngress: +{% for rule in tcp_rules %} - IpProtocol: "tcp" - FromPort: "27017" - ToPort: "27017" - CidrIp: "0.0.0.0/0" + FromPort: "{{rule.from_}}" + ToPort: "{{rule.to_}}" + CidrIp: "{{rule.cidr}}" +{% endfor %} +{% for rule in udp_rules %} + - IpProtocol: "udp" + FromPort: "{{rule.from_}}" + ToPort: "{{rule.to_}}" + CidrIp: "{{rule.cidr}}" +{% endfor %} +{% endif %} DatabaseIPAddress: Type: AWS::EC2::EIP DatabaseIPAssoc : diff --git a/trove/templates/mysql/heat.template b/trove/templates/mysql/heat.template index b692d96ed5..65641e8bd1 100644 --- a/trove/templates/mysql/heat.template +++ b/trove/templates/mysql/heat.template @@ -23,7 +23,7 @@ Resources: Type: OS::Neutron::Port Properties: network_id: "{{ port.net_id }}" - security_groups: [{Ref: MySqlDbaasSG}] + security_groups: [{Ref: DatastoreSG}] {% if port.fixed_ip %} fixed_ips: [{"ip_address": "{{ port.fixed_ip }}"}] {% endif %} @@ -51,7 +51,7 @@ Resources: {% if ifaces %} NetworkInterfaces: [{{ ifaces|join(', ') }}] {% else %} - SecurityGroups: [{Ref: MySqlDbaasSG}] + SecurityGroups: [{Ref: DatastoreSG}] {% endif %} UserData: Fn::Base64: @@ -75,15 +75,25 @@ Resources: VolumeId: {Ref: DataVolume} Device: /dev/vdb {% endif %} - MySqlDbaasSG: + DatastoreSG: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Default Security group for MySQL +{% if tcp_rules or udp_rules %} SecurityGroupIngress: +{% for rule in tcp_rules %} - IpProtocol: "tcp" - FromPort: "3306" - ToPort: "3306" - CidrIp: "0.0.0.0/0" + FromPort: "{{rule.from_}}" + ToPort: "{{rule.to_}}" + CidrIp: "{{rule.cidr}}" +{% endfor %} +{% for rule in udp_rules %} + - IpProtocol: "udp" + FromPort: "{{rule.from_}}" + ToPort: "{{rule.to_}}" + CidrIp: "{{rule.cidr}}" +{% endfor %} +{% endif %} DatabaseIPAddress: Type: AWS::EC2::EIP DatabaseIPAssoc : diff --git a/trove/templates/redis/heat.template b/trove/templates/redis/heat.template index 5e57a4aff9..0e369ec21e 100644 --- a/trove/templates/redis/heat.template +++ b/trove/templates/redis/heat.template @@ -23,7 +23,7 @@ Resources: Type: OS::Neutron::Port Properties: network_id: "{{ port.net_id }}" - security_groups: [{Ref: DBaaSSG}] + security_groups: [{Ref: DatastoreSG}] {% if port.fixed_ip %} fixed_ips: [{"ip_address": "{{ port.fixed_ip }}"}] {% endif %} @@ -51,7 +51,7 @@ Resources: {% if ifaces %} NetworkInterfaces: [{{ ifaces|join(', ') }}] {% else %} - SecurityGroups: [{Ref: DBaaSSG}] + SecurityGroups: [{Ref: DatastoreSG}] {% endif %} UserData: Fn::Base64: @@ -75,15 +75,25 @@ Resources: VolumeId: {Ref: DataVolume} Device: /dev/vdb {% endif %} - DBaaSSG: + DatastoreSG: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Default Security group for Redis +{% if tcp_rules or udp_rules %} SecurityGroupIngress: +{% for rule in tcp_rules %} - IpProtocol: "tcp" - FromPort: "6379" - ToPort: "6379" - CidrIp: "0.0.0.0/0" + FromPort: "{{rule.from_}}" + ToPort: "{{rule.to_}}" + CidrIp: "{{rule.cidr}}" +{% endfor %} +{% for rule in udp_rules %} + - IpProtocol: "udp" + FromPort: "{{rule.from_}}" + ToPort: "{{rule.to_}}" + CidrIp: "{{rule.cidr}}" +{% endfor %} +{% endif %} DatabaseIPAddress: Type: AWS::EC2::EIP DatabaseIPAssoc : diff --git a/trove/tests/unittests/common/test_template.py b/trove/tests/unittests/common/test_template.py index 180bb54bd6..3f55f1134c 100644 --- a/trove/tests/unittests/common/test_template.py +++ b/trove/tests/unittests/common/test_template.py @@ -103,3 +103,34 @@ class HeatTemplateLoadTest(testtools.TestCase): self.assertIsNotNone(redis_tmplt) self.assertIsNotNone(cassandra_tmpl) self.assertIsNotNone(mongo_tmpl) + + def test_render_templates_with_ports_from_config(self): + mysql_tmpl = template.load_heat_template('mysql') + tcp_rules = [{'cidr': "0.0.0.0/0", + 'from_': 3306, + 'to_': 3309}, + {'cidr': "0.0.0.0/0", + 'from_': 3320, + 'to_': 33022}] + output = mysql_tmpl.render( + volume_support=True, + ifaces=[], ports=[], + tcp_rules=tcp_rules, + udp_rules=[]) + self.assertIsNotNone(output) + self.assertIn('FromPort: "3306"', output) + self.assertIn('ToPort: "3309"', output) + self.assertIn('CidrIp: "0.0.0.0/0"', output) + self.assertIn('FromPort: "3320"', output) + self.assertIn('ToPort: "33022"', output) + + def test_no_rules_if_no_ports(self): + mysql_tmpl = template.load_heat_template('mysql') + output = mysql_tmpl.render( + volume_support=True, + ifaces=[], ports=[], + tcp_rules=[], + udp_rules=[]) + self.assertIsNotNone(output) + self.assertNotIn('- IpProtocol: "tcp"', output) + self.assertNotIn('- IpProtocol: "udp"', output)