From 326b071db1336ee98f48bb8f57672aaaf6a656c5 Mon Sep 17 00:00:00 2001 From: Gary Kotton Date: Wed, 31 Jan 2018 16:02:12 +0200 Subject: [PATCH] NSX|V: default support for IGMP traffic Enable IGMP traffic to pass by default. This is added to the default section created by the plugin. Change-Id: I0320cc8bf81cda22633637ee9eac4a57fc3b4086 --- vmware_nsx/plugins/nsx_v/plugin.py | 22 ++++++++++++++ .../nsx_v/vshield/securitygroup_utils.py | 10 ++++++- vmware_nsx/plugins/nsx_v/vshield/vcns.py | 30 +++++++++++++++++++ .../tests/unit/nsx_v/vshield/fake_vcns.py | 3 ++ 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/vmware_nsx/plugins/nsx_v/plugin.py b/vmware_nsx/plugins/nsx_v/plugin.py index c5f99c4592..9f7760921f 100644 --- a/vmware_nsx/plugins/nsx_v/plugin.py +++ b/vmware_nsx/plugins/nsx_v/plugin.py @@ -526,6 +526,25 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin, logged=cfg.CONF.nsxv.log_security_groups_allowed_traffic) rule_list.append(rule_config) + igmp_names = ['IGMP Membership Query', 'IGMP V2 Membership Report', + 'IGMP V3 Membership Report', 'IGMP Leave Group'] + igmp_ids = [] + for name in igmp_names: + igmp_id = self._get_appservice_id(name) + if igmp_id: + igmp_ids.append(igmp_id) + if igmp_ids: + rules = [{'name': 'Default IGMP rule for OS Security Groups', + 'action': 'allow', + 'service_ids': igmp_ids}] + for rule in rules: + rule_config = self.nsx_sg_utils.get_rule_config( + applied_to_ids, rule['name'], rule['action'], + applied_to_type, + application_services=rule['service_ids'], + logged=cfg.CONF.nsxv.log_security_groups_allowed_traffic) + rule_list.append(rule_config) + # Default security-group rules block_rule = self.nsx_sg_utils.get_rule_config( [self.sg_container_id], 'Block All', 'deny', @@ -4674,3 +4693,6 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin, def update_housekeeper(self, context, name, housekeeper): self.housekeeper.run(context, name) return self.housekeeper.get(name) + + def _get_appservice_id(self, name): + return self.nsx_v.vcns.get_application_id(name) diff --git a/vmware_nsx/plugins/nsx_v/vshield/securitygroup_utils.py b/vmware_nsx/plugins/nsx_v/vshield/securitygroup_utils.py index 5d7c9e183a..ed62066ca4 100644 --- a/vmware_nsx/plugins/nsx_v/vshield/securitygroup_utils.py +++ b/vmware_nsx/plugins/nsx_v/vshield/securitygroup_utils.py @@ -60,7 +60,8 @@ class NsxSecurityGroupUtils(object): def get_rule_config(self, applied_to_ids, name, action='allow', applied_to='SecurityGroup', source=None, destination=None, services=None, - flags=None, logged=False, tag=None): + flags=None, logged=False, tag=None, + application_services=None): """Helper method to create a nsx rule dict.""" ruleTag = et.Element('rule') ruleTag.attrib['logged'] = 'true' if logged else 'false' @@ -116,6 +117,13 @@ class NsxSecurityGroupUtils(object): svcPortTag = et.SubElement(svcTag, 'icmpCode') svcPortTag.text = str(icmpcode) + if application_services: + s = et.SubElement(ruleTag, 'services') + for application_service in application_services: + svcTag = et.SubElement(s, 'service') + svcProtocolTag = et.SubElement(svcTag, 'value') + svcProtocolTag.text = str(application_service) + if flags: if flags.get('ethertype') is not None: pktTag = et.SubElement(ruleTag, 'packetType') diff --git a/vmware_nsx/plugins/nsx_v/vshield/vcns.py b/vmware_nsx/plugins/nsx_v/vshield/vcns.py index 4cee421647..749119e450 100644 --- a/vmware_nsx/plugins/nsx_v/vshield/vcns.py +++ b/vmware_nsx/plugins/nsx_v/vshield/vcns.py @@ -121,6 +121,7 @@ class Vcns(object): insecure=insecure, timeout=cfg.CONF.nsxv.nsx_transaction_timeout) self._nsx_version = None self._normalized_scoping_objects = None + self._normalized_global_objects = None @retry_upon_exception(exceptions.ServiceConflict) def _client_request(self, client, method, uri, @@ -1155,3 +1156,32 @@ class Vcns(object): def delete_bgp_routing_config(self, edge_id): uri = self._build_uri_path(edge_id, BGP_ROUTING_CONFIG) return self.do_request(HTTP_DELETE, uri) + + def get_global_objects(self): + uri = '%s/application/scope/globalroot-0' % SERVICES_PREFIX + h, scoping_objects = self.do_request(HTTP_GET, uri, decode=False, + format='xml') + return scoping_objects + + def _globalobjects_lookup(self, name, use_cache=False): + """Return objectId a specific name in the NSX global objects.""" + # used cached scoping objects during plugin init since it is + # a big structure to retrieve and parse each time. + if use_cache and self._normalized_global_objects is not None: + # Use the cached data + root = self._normalized_global_objects + else: + # Not using cache, or we do want to use it, + # but it was not saved yet: + # So get the data from the NSX and parse it + so_list = self.get_global_objects() + root = utils.normalize_xml(so_list) + # Save it for possible usage next time (even if not using cache) + self._normalized_global_objects = root + + for obj in root.iter('application'): + if obj.find('name').text == name: + return obj.find('objectId').text + + def get_application_id(self, name): + return self._globalobjects_lookup(name, use_cache=True) diff --git a/vmware_nsx/tests/unit/nsx_v/vshield/fake_vcns.py b/vmware_nsx/tests/unit/nsx_v/vshield/fake_vcns.py index 8cbcddd689..f7b9884b78 100644 --- a/vmware_nsx/tests/unit/nsx_v/vshield/fake_vcns.py +++ b/vmware_nsx/tests/unit/nsx_v/vshield/fake_vcns.py @@ -1614,3 +1614,6 @@ class FakeVcns(object): header = {'status': 200} response = '' return header, response + + def get_application_id(self, name): + return 'application-123'