diff --git a/vmware_nsx/neutron/plugins/vmware/plugins/nsx_v.py b/vmware_nsx/neutron/plugins/vmware/plugins/nsx_v.py index 591a4854a4..842db90cd8 100644 --- a/vmware_nsx/neutron/plugins/vmware/plugins/nsx_v.py +++ b/vmware_nsx/neutron/plugins/vmware/plugins/nsx_v.py @@ -127,6 +127,7 @@ class NsxVPluginV2(agents_db.AgentDbMixin, self.nsx_v) # Ensure that edges do concurrency self._ensure_lock_operations() + self.sg_container_id = self._create_security_group_container() self._validate_config() self._create_cluster_default_fw_rules() @@ -139,6 +140,17 @@ class NsxVPluginV2(agents_db.AgentDbMixin, nsx_v_md_proxy.NsxVMetadataProxyHandler(self) if has_metadata_cfg else None) + def _create_security_group_container(self): + name = "OpenStack Security Group container" + container_id = self.nsx_v.vcns.get_security_group_id(name) + if not container_id: + description = ("OpenStack Security Group Container, " + "managed by Neutron nsx-v plugin.") + container = {"securitygroup": {"name": name, + "description": description}} + h, container_id = self.nsx_v.vcns.create_security_group(container) + return container_id + def _create_cluster_default_fw_rules(self): # default cluster rules rules = [{'name': 'Default DHCP rule for OS Security Groups', @@ -148,10 +160,7 @@ class NsxVPluginV2(agents_db.AgentDbMixin, {'name': 'ICMPv6 neighbor protocol for Security Groups', 'action': 'allow', 'services': [('58', None, '135', None), - ('58', None, '136', None)]}, - {'name': 'Block All', - 'action': 'deny', - 'services': []}] + ('58', None, '136', None)]}] rule_list = [] for cluster_moid in cfg.CONF.nsxv.cluster_moid: @@ -161,6 +170,10 @@ class NsxVPluginV2(agents_db.AgentDbMixin, 'ClusterComputeResource', services=rule['services']) rule_list.append(rule_config) + block_rule = self.nsx_sg_utils.get_rule_config( + self.sg_container_id, 'Block All', 'deny') + rule_list.append(block_rule) + if rule_list: section_name = 'OS Cluster Security Group section' section_id = self.nsx_v.vcns.get_section_id(section_name) @@ -1754,6 +1767,10 @@ class NsxVPluginV2(agents_db.AgentDbMixin, nsxv_db.add_neutron_nsx_rule_mapping( context.session, _neutron_id, _nsx_id) + # Add this Security Group to the Security Groups container + self._add_member_to_security_group(self.sg_container_id, + nsx_sg_id) + except Exception: with excutils.save_and_reraise_exception(): # Delete the nsx rule section diff --git a/vmware_nsx/neutron/plugins/vmware/vshield/vcns.py b/vmware_nsx/neutron/plugins/vmware/vshield/vcns.py index 94e57b4826..d44263a4c1 100644 --- a/vmware_nsx/neutron/plugins/vmware/vshield/vcns.py +++ b/vmware_nsx/neutron/plugins/vmware/vshield/vcns.py @@ -459,6 +459,15 @@ class Vcns(object): uri = '%s/%s?force=true' % (SECURITYGROUP_PREFIX, securitygroup_id) return self.do_request(HTTP_DELETE, uri, format='xml', decode=False) + def get_security_group_id(self, sg_name): + """Returns NSXv security group id which match the given name.""" + uri = '%s/scope/globalroot-0' % SECURITYGROUP_PREFIX + h, c = self.do_request(HTTP_GET, uri, format='xml', decode=False) + root = et.fromstring(c) + for sg in root.iter('securitygroup'): + if sg.find('name').text == sg_name: + return sg.find('objectId').text + def create_section(self, type, request): """Creates a layer 3 or layer 2 section in nsx rule table. diff --git a/vmware_nsx/neutron/tests/unit/vmware/test_nsx_v_plugin.py b/vmware_nsx/neutron/tests/unit/vmware/test_nsx_v_plugin.py index 774a25623e..a152c742e5 100644 --- a/vmware_nsx/neutron/tests/unit/vmware/test_nsx_v_plugin.py +++ b/vmware_nsx/neutron/tests/unit/vmware/test_nsx_v_plugin.py @@ -1480,6 +1480,7 @@ class NsxVTestSecurityGroup(ext_sg.TestSecurityGroups, self._delete('ports', port['id']) def test_vnic_security_group_membership(self): + p = manager.NeutronManager.get_plugin() self.fc2.add_member_to_security_group = ( mock.Mock().add_member_to_security_group) self.fc2.remove_member_from_security_group = ( @@ -1491,6 +1492,9 @@ class NsxVTestSecurityGroup(ext_sg.TestSecurityGroups, vnic_id = '%s.%03d' % (device_id, port_index) with self.port(device_id=device_id, device_owner='compute:None') as port: + (self.fc2.add_member_to_security_group + .assert_called_once_with(p.sg_container_id, nsx_sg_id)) + self.fc2.add_member_to_security_group.reset_mock() data = {'port': {'vnic_index': port_index}} self.new_update_request('ports', data, port['port']['id']).get_response(self.api) diff --git a/vmware_nsx/neutron/tests/unit/vmware/vshield/fake_vcns.py b/vmware_nsx/neutron/tests/unit/vmware/vshield/fake_vcns.py index 0ef7284895..8857b0cba5 100644 --- a/vmware_nsx/neutron/tests/unit/vmware/vshield/fake_vcns.py +++ b/vmware_nsx/neutron/tests/unit/vmware/vshield/fake_vcns.py @@ -824,6 +824,11 @@ class FakeVcns(object): status, response = 200, '' return ({'status': status}, response) + def get_security_group_id(self, sg_name): + for k, v in self._securitygroups.items(): + if k not in ('ids', 'names') and v['name'] == sg_name: + return k + def create_section(self, type, request): section = ET.fromstring(request) section_name = section.attrib.get('name') @@ -910,6 +915,13 @@ class FakeVcns(object): 'etag': self._sections[section_id]['etag']} return (headers, response) + def get_section_id(self, section_name): + self._sections = {'section_ids': 0, 'rule_ids': 0, 'names': set()} + for k, v in self._sections.items(): + if (k not in ('section_ids', 'rule_ids', 'names') + and v['name'] == section_name): + return k + def remove_rule_from_section(self, section_uri, rule_id): section_id = self._get_section_id_from_uri(section_uri) if section_id not in self._sections: