Security Groups implementation

Change-Id: I415938e53d4656b376812dc85e2e9bb6d9986fe9
This commit is contained in:
Roey Chen 2015-07-20 15:23:18 -07:00
parent 7e2205e9ab
commit 78ba18f6d2
9 changed files with 621 additions and 17 deletions

View File

@ -1,2 +1,2 @@
28430956782d
393bf843b96
53a3254aa95e

View File

@ -0,0 +1,47 @@
# Copyright 2015 OpenStack Foundation
#
# 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.
#
"""nsxv3_security_groups
Revision ID: 28430956782d
Revises: 53a3254aa95e
Create Date: 2015-08-24 18:19:09.397813
"""
# revision identifiers, used by Alembic.
revision = '28430956782d'
down_revision = '53a3254aa95e'
from alembic import op
import sqlalchemy as sa
def upgrade():
op.create_table(
'neutron_nsx_firewall_section_mappings',
sa.Column('neutron_id', sa.String(36), nullable=False),
sa.Column('nsx_id', sa.String(36), nullable=False),
sa.ForeignKeyConstraint(['neutron_id'], ['securitygroups.id'],
ondelete='CASCADE'),
sa.PrimaryKeyConstraint('neutron_id'))
op.create_table(
'neutron_nsx_rule_mappings',
sa.Column('neutron_id', sa.String(36), nullable=False),
sa.Column('nsx_id', sa.String(36), nullable=False),
sa.ForeignKeyConstraint(['neutron_id'], ['securitygrouprules.id'],
ondelete='CASCADE'),
sa.PrimaryKeyConstraint('neutron_id'))

View File

@ -89,6 +89,34 @@ class NeutronNsxSecurityGroupMapping(model_base.BASEV2):
nsx_id = sa.Column(sa.String(36), primary_key=True)
class NeutronNsxFirewallSectionMapping(model_base.BASEV2):
"""Backend mappings for Neutron Security-group associated fw sections."""
__tablename__ = 'neutron_nsx_firewall_section_mappings'
neutron_id = sa.Column(sa.String(36),
sa.ForeignKey('securitygroups.id',
ondelete='CASCADE'),
primary_key=True,
nullable=False)
nsx_id = sa.Column(sa.String(36), nullable=False)
class NeutronNsxRuleMapping(model_base.BASEV2):
"""Backend mappings for firewall rules.
This class maps a neutron security group rule with NSX firewall rule.
"""
__tablename__ = 'neutron_nsx_rule_mappings'
neutron_id = sa.Column(sa.String(36),
sa.ForeignKey('securitygrouprules.id',
ondelete="CASCADE"),
primary_key=True,
nullable=False)
nsx_id = sa.Column(sa.String(36), nullable=False)
class NeutronNsxPortMapping(model_base.BASEV2):
"""Represents the mapping between neutron and nsx port uuids."""

View File

@ -86,7 +86,7 @@ def create_resource(resource, data):
verify=verify, headers=headers,
data=jsonutils.dumps(data),
cert=cfg.CONF.nsx_v3.ca_file)
_validate_result(result, [requests.codes.created],
_validate_result(result, [requests.codes.created, requests.codes.ok],
_("creating resource at: %s") % resource)
return result.json()

View File

@ -0,0 +1,193 @@
# Copyright 2015 OpenStack Foundation
# All Rights Reserved
#
# 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.
"""
NSX-V3 Distributed Firewall
"""
from vmware_nsx.neutron.plugins.vmware.common import exceptions as nsx_exc
from vmware_nsx.neutron.plugins.vmware.common import utils
from vmware_nsx.neutron.plugins.vmware.nsxlib.v3 import client as nsclient
# firewall section types
LAYER3 = 'LAYER3'
# firewall rule actions
ALLOW = 'ALLOW'
DROP = 'DROP'
REJECT = 'REJECT'
# filtering operators
EQUALS = 'EQUALS'
NSGROUP = 'NSGroup'
LOGICAL_SWITCH = 'LogicalSwitch'
LOGICAL_PORT = 'LogicalPort'
IPV4ADDRESS = 'IPv4Address'
IPV6ADDRESS = 'IPv6Address'
IN = 'IN'
OUT = 'OUT'
# NSServices resource types
L4_PORT_SET_NSSERVICE = 'L4PortSetNSService'
ICMP_TYPE_NSSERVICE = 'ICMPTypeNSService'
IP_PROTOCOL_NSSERVICE = 'IPProtocolNSService'
TCP = 'TCP'
UDP = 'UDP'
ICMPV4 = 'ICMPv4'
ICMPV6 = 'ICMPv6'
IPV4 = 'IPV4'
IPV6 = 'IPV6'
def get_nsservice(resource_type, **properties):
service = {'resource_type': resource_type}
service.update(properties)
return {'service': service}
def create_nsgroup(display_name, description, tags):
body = {'display_name': display_name,
'description': description,
'tags': tags}
return nsclient.create_resource('ns-groups', body)
def list_nsgroups():
return nsclient.get_resource('ns-groups')
@utils.retry_upon_exception_nsxv3(nsx_exc.StaleRevision)
def update_nsgroup(nsgroup_id, display_name, description):
nsgroup = read_nsgroup(nsgroup_id)
nsgroup.update({'display_name': display_name,
'description': description})
return nsclient.update_resource('ns-groups/%s' % nsgroup_id, nsgroup)
@utils.retry_upon_exception_nsxv3(nsx_exc.StaleRevision)
def add_nsgroup_member(nsgroup_id, target_type, target_id):
nsgroup = read_nsgroup(nsgroup_id)
if 'members' not in nsgroup:
nsgroup['members'] = []
nsgroup['members'].append({'target_property': 'id',
'target_type': target_type,
'op': EQUALS,
'value': target_id})
return nsclient.update_resource('ns-groups/%s' % nsgroup_id, nsgroup)
@utils.retry_upon_exception_nsxv3(nsx_exc.StaleRevision)
def remove_nsgroup_member(nsgroup_id, target_id):
nsgroup = read_nsgroup(nsgroup_id)
for i, member in enumerate(nsgroup.get('members', [])):
if target_id == member['value']:
break
else:
return
del nsgroup['members'][i]
return nsclient.update_resource('ns-groups/%s' % nsgroup_id, nsgroup)
def read_nsgroup(nsgroup_id):
return nsclient.get_resource('ns-groups/%s' % nsgroup_id)
def delete_nsgroup(nsgroup_id):
return nsclient.delete_resource('ns-groups/%s' % nsgroup_id)
def _build_section(display_name, description, applied_tos, tags):
return {'display_name': display_name,
'description': description,
'stateful': True,
'section_type': LAYER3,
'applied_tos': [get_nsgroup_reference(t_id)
for t_id in applied_tos],
'tags': tags}
def create_empty_section(display_name, description, applied_tos, tags):
resource = 'firewall/sections'
body = _build_section(display_name, description, applied_tos, tags)
return nsclient.create_resource(resource, body)
@utils.retry_upon_exception_nsxv3(nsx_exc.StaleRevision)
def update_section(section_id, display_name, description, applied_tos=None):
resource = 'firewall/sections/%s' % section_id
section = read_section(section_id)
section.update({'display_name': display_name,
'description': description})
if applied_tos is not None:
section['applied_tos'] = applied_tos
return nsclient.update_resource(resource, section)
def read_section(section_id):
resource = 'firewall/sections/%s' % section_id
return nsclient.get_resource(resource)
def list_sections():
resource = 'firewall/sections'
return nsclient.get_resource(resource)
def delete_section(section_id):
resource = 'firewall/sections/%s?cascade=true' % section_id
return nsclient.delete_resource(resource)
def get_nsgroup_reference(nsgroup_id):
return {'target_id': nsgroup_id,
'target_type': NSGROUP}
def get_ip_cidr_reference(ip_cidr_block, ip_protocol):
target_type = IPV4ADDRESS if ip_protocol == IPV4 else IPV6ADDRESS
return {'target_id': ip_cidr_block,
'target_type': target_type}
def get_firewall_rule_dict(display_name, source, destination, direction,
ip_protocol, service, action):
return {'display_name': display_name,
'sources': [source] if source else [],
'destinations': [destination] if destination else [],
'direction': direction,
'ip_protocol': ip_protocol,
'services': [service] if service else [],
'action': action}
def add_rule_in_section(rule, section_id):
resource = 'firewall/sections/%s/rules' % section_id
return nsclient.create_resource(resource, rule)
def add_rules_in_section(rules, section_id):
resource = 'firewall/sections/%s/rules?action=create_multiple' % section_id
return nsclient.create_resource(resource, {'rules': rules})
def delete_rule(section_id, rule_id):
resource = 'firewall/sections/%s/rules/%s' % (section_id, rule_id)
return nsclient.delete_resource(resource)

View File

@ -0,0 +1,172 @@
# Copyright 2015 OpenStack Foundation
# All Rights Reserved
#
# 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.
"""
NSX-V3 Plugin security integration module
"""
from neutron.db import securitygroups_db
from vmware_nsx.neutron.plugins.vmware.dbexts import nsx_models
from vmware_nsx.neutron.plugins.vmware.nsxlib.v3 import dfw_api as firewall
def _get_l4_protocol_name(proto_num):
if proto_num == 6:
return firewall.TCP
elif proto_num == 17:
return firewall.UDP
elif proto_num == 1:
return firewall.ICMPV4
def _decide_service(sg_rule):
ip_proto = securitygroups_db.IP_PROTOCOL_MAP.get(sg_rule['protocol'],
sg_rule['protocol'])
l4_protocol = _get_l4_protocol_name(ip_proto)
if l4_protocol in [firewall.TCP, firewall.UDP]:
# If port_range_min is not specified then we assume all ports are
# matched, relying on neutron to perform validation.
if sg_rule['port_range_min'] is None:
source_ports = []
else:
source_ports = ['%(port_range_min)s-%(port_range_max)s' % sg_rule]
return firewall.get_nsservice(firewall.L4_PORT_SET_NSSERVICE,
l4_protocol=l4_protocol,
source_ports=source_ports)
elif l4_protocol == firewall.ICMPV4:
return firewall.get_nsservice(firewall.ICMP_TYPE_NSSERVICE,
protocol=l4_protocol,
icmp_type=sg_rule['port_range_min'],
icmp_code=sg_rule['port_range_max'])
elif ip_proto is not None:
return firewall.get_nsservice(firewall.IP_PROTOCOL_NSSERVICE,
protocol_number=ip_proto)
def _get_fw_rule_from_sg_rule(sg_rule, nsgroup_id, rmt_nsgroup_id):
# IPV4 or IPV6
ip_protocol = sg_rule['ethertype'].upper()
direction = (
firewall.IN if sg_rule['direction'] == 'ingress' else firewall.OUT)
source = None
local_group = firewall.get_nsgroup_reference(nsgroup_id)
if sg_rule['remote_ip_prefix'] is not None:
source = firewall.get_ip_cidr_reference(sg_rule['remote_ip_prefix'],
ip_protocol)
destination = local_group
else:
if rmt_nsgroup_id:
source = firewall.get_nsgroup_reference(rmt_nsgroup_id)
destination = local_group
if direction == firewall.OUT:
source, destination = destination, source
service = _decide_service(sg_rule)
name = sg_rule['id']
return firewall.get_firewall_rule_dict(name, source,
destination, direction,
ip_protocol, service,
firewall.ALLOW)
def create_firewall_rules(context, section_id, nsgroup_id,
security_group_rules):
# 1. translate rules
# 2. insert in section
# 3. save mappings
firewall_rules = []
for sg_rule in security_group_rules:
remote_nsgroup_id = _get_remote_nsg_mapping(
context, sg_rule, nsgroup_id)
fw_rule = _get_fw_rule_from_sg_rule(
sg_rule, nsgroup_id, remote_nsgroup_id)
firewall_rules.append(
firewall.add_rule_in_section(fw_rule, section_id))
return {'rules': firewall_rules}
def get_nsgroup_name(security_group):
# NOTE(roeyc): We add the security-group id to the NSGroup name,
# for usability purposes.
return '%(name)s - %(id)s' % security_group
def save_sg_rule_mappings(session, firewall_rules):
# REVISIT(roeyc): This method should take care db access only.
rules = [(rule['display_name'], rule['id']) for rule in firewall_rules]
with session.begin(subtransactions=True):
for neutron_id, nsx_id in rules:
mapping = nsx_models.NeutronNsxRuleMapping(
neutron_id=neutron_id, nsx_id=nsx_id)
session.add(mapping)
return mapping
def save_sg_mappings(session, sg_id, nsgroup_id, section_id):
with session.begin(subtransactions=True):
session.add(
nsx_models.NeutronNsxFirewallSectionMapping(neutron_id=sg_id,
nsx_id=section_id))
session.add(
nsx_models.NeutronNsxSecurityGroupMapping(neutron_id=sg_id,
nsx_id=nsgroup_id))
def get_sg_rule_mapping(session, rule_id):
rule_mapping = session.query(nsx_models.NeutronNsxRuleMapping).filter_by(
neutron_id=rule_id).one()
return rule_mapping.nsx_id
def get_sg_mappings(session, sg_id):
nsgroup_mapping = session.query(nsx_models.NeutronNsxSecurityGroupMapping
).filter_by(neutron_id=sg_id).one()
section_mapping = session.query(nsx_models.NeutronNsxFirewallSectionMapping
).filter_by(neutron_id=sg_id).one()
return nsgroup_mapping.nsx_id, section_mapping.nsx_id
def _get_remote_nsg_mapping(context, sg_rule, nsgroup_id):
remote_nsgroup_id = None
remote_group_id = sg_rule.get('remote_group_id')
# skip unnecessary db access when possible
if remote_group_id == sg_rule['security_group_id']:
remote_nsgroup_id = nsgroup_id
elif remote_group_id:
remote_nsgroup_id, _ = get_sg_mappings(context.session,
remote_group_id)
return remote_nsgroup_id
def update_lport_with_security_groups(context, lport_id, original, updated):
added = set(updated) - set(original)
removed = set(original) - set(updated)
for sg_id in added:
nsgroup_id, _ = get_sg_mappings(context.session, sg_id)
firewall.add_nsgroup_member(
nsgroup_id, firewall.LOGICAL_PORT, lport_id)
for sg_id in removed:
nsgroup_id, _ = get_sg_mappings(context.session, sg_id)
firewall.remove_nsgroup_member(
nsgroup_id, lport_id)

View File

@ -32,6 +32,7 @@ from neutron.extensions import extra_dhcp_opt as edo_ext
from neutron.extensions import l3
from neutron.extensions import portbindings as pbin
from neutron.extensions import providernet as pnet
from neutron.extensions import securitygroup as ext_sg
from neutron.common import constants as const
from neutron.common import exceptions as n_exc
@ -55,6 +56,8 @@ from vmware_nsx.neutron.plugins.vmware.common import exceptions as nsx_exc
from vmware_nsx.neutron.plugins.vmware.common import utils
from vmware_nsx.neutron.plugins.vmware.dbexts import db as nsx_db
from vmware_nsx.neutron.plugins.vmware.nsxlib import v3 as nsxlib
from vmware_nsx.neutron.plugins.vmware.nsxlib.v3 import dfw_api as firewall
from vmware_nsx.neutron.plugins.vmware.nsxlib.v3 import security
LOG = log.getLogger(__name__)
@ -66,8 +69,6 @@ class NsxV3Plugin(db_base_plugin_v2.NeutronDbPluginV2,
portbindings_db.PortBindingMixin,
agentschedulers_db.DhcpAgentSchedulerDbMixin,
extradhcpopt_db.ExtraDhcpOptMixin):
# NOTE(salv-orlando): Security groups are not actually implemented by this
# plugin at the moment
__native_bulk_support = True
__native_pagination_support = True
@ -438,6 +439,7 @@ class NsxV3Plugin(db_base_plugin_v2.NeutronDbPluginV2,
nsx_db.add_neutron_nsx_port_mapping(
context.session, neutron_db['id'],
neutron_db['network_id'], result['id'])
return result
def create_port(self, context, port):
dhcp_opts = port['port'].get(edo_ext.EXTRADHCPOPTS, [])
@ -456,7 +458,7 @@ class NsxV3Plugin(db_base_plugin_v2.NeutronDbPluginV2,
if not self._network_is_external(
context, port['port']['network_id']):
self._create_port_at_the_backend(
lport = self._create_port_at_the_backend(
context, neutron_db, port['port'])
self._process_portbindings_create_and_update(context,
port['port'],
@ -466,11 +468,15 @@ class NsxV3Plugin(db_base_plugin_v2.NeutronDbPluginV2,
if (pbin.PROFILE in port['port'] and
attributes.is_attr_set(port['port'][pbin.PROFILE])):
neutron_db[pbin.PROFILE] = port['port'][pbin.PROFILE]
sgids = self._get_security_groups_on_port(context, port)
self._process_port_create_security_group(
context, neutron_db, sgids)
self._process_port_create_extra_dhcp_opts(context, neutron_db,
dhcp_opts)
sgids = self._get_security_groups_on_port(context, port)
if sgids is not None:
self._process_port_create_security_group(
context, neutron_db, sgids)
security.update_lport_with_security_groups(
context, lport['id'], [], sgids)
return neutron_db
def delete_port(self, context, port_id, l3_port_check=True):
@ -497,12 +503,15 @@ class NsxV3Plugin(db_base_plugin_v2.NeutronDbPluginV2,
self._update_extra_dhcp_opts_on_port(context, id, port,
updated_port)
sec_grp_updated = self.update_security_group_on_port(
context, id, port, original_port,
updated_port)
context, id, port, original_port, updated_port)
try:
nsxlib.update_logical_port(
nsx_lport_id, name=port['port'].get('name'),
admin_state=port['port'].get('admin_state_up'))
security.update_lport_with_security_groups(
context, nsx_lport_id,
original_port.get(ext_sg.SECURITYGROUPS, []),
updated_port.get(ext_sg.SECURITYGROUPS, []))
except nsx_exc.ManagerError:
# In case if there is a failure on NSX-v3 backend, rollback the
# previous update operation on neutron side.
@ -517,6 +526,8 @@ class NsxV3Plugin(db_base_plugin_v2.NeutronDbPluginV2,
context, id, {'port': original_port}, updated_port,
original_port)
#TODO(roeyc): add port to nsgroups
return updated_port
def create_router(self, context, router):
@ -616,10 +627,128 @@ class NsxV3Plugin(db_base_plugin_v2.NeutronDbPluginV2,
return super(NsxV3Plugin, self).remove_router_interface(
context, router_id, interface_info)
def create_security_group_rule_bulk(self, context, security_group_rules):
return super(NsxV3Plugin, self).create_security_group_rule_bulk_native(
context, security_group_rules)
def extend_port_dict_binding(self, port_res, port_db):
super(NsxV3Plugin, self).extend_port_dict_binding(port_res, port_db)
port_res[pbin.VNIC_TYPE] = pbin.VNIC_NORMAL
def create_security_group(self, context, security_group, default_sg=False):
secgroup = security_group['security_group']
secgroup['id'] = uuidutils.generate_uuid()
tags = utils.build_v3_tags_payload(secgroup)
name = security.get_nsgroup_name(secgroup)
ns_group = None
try:
# NOTE(roeyc): We first create the nsgroup so that once the sg is
# saved into db its already backed up by an nsx resource.
ns_group = firewall.create_nsgroup(
name, secgroup['description'], tags)
# security-group rules are located in a dedicated firewall section.
firewall_section = firewall.create_empty_section(
name, secgroup.get('description', ''), [ns_group['id']], tags)
# REVISIT(roeyc): Idealy, at this point we need not be under an
# open db transactions, however, unittests fail if omitting
# subtransactions=True.
with context.session.begin(subtransactions=True):
secgroup_db = (
super(NsxV3Plugin, self).create_security_group(
context, security_group, default_sg))
security.save_sg_mappings(context.session,
secgroup_db['id'],
ns_group['id'],
firewall_section['id'])
except nsx_exc.ManagerError:
with excutils.save_and_reraise_exception():
LOG.exception(_LE("Unable to create security-group on the "
"backend."))
if ns_group:
firewall.delete_nsgroup(ns_group['id'])
except Exception:
with excutils.save_and_reraise_exception():
LOG.debug("Neutron failed to create security-group, "
"deleting backend resources: "
"section %s, ns-group %s.",
firewall_section['id'], ns_group['id'])
firewall.delete_nsgroup(ns_group['id'])
firewall.delete_section(firewall_section['id'])
try:
sg_rules = secgroup_db['security_group_rules']
# translate and creates firewall rules.
rules = security.create_firewall_rules(
context, firewall_section['id'], ns_group['id'], sg_rules)
security.save_sg_rule_mappings(context.session, rules['rules'])
except nsx_exc.ManagerError:
with excutils.save_and_reraise_exception():
LOG.exception(_LE("Failed to create backend firewall rules "
" for security-group %(name)s (%(id)s), "
"rolling back changes."), secgroup_db)
# default security group deletion requires admin context
if default_sg:
context = context.elevated()
super(NsxV3Plugin, self).delete_security_group(
context, secgroup_db['id'])
firewall.delete_nsgroup(ns_group['id'])
firewall.delete_section(firewall_section['id'])
return secgroup_db
def update_security_group(self, context, id, security_group):
nsgroup_id, section_id = security.get_sg_mappings(context.session, id)
original_security_group = self.get_security_group(
context, id, fields=['id', 'name', 'description'])
updated_security_group = (
super(NsxV3Plugin, self).update_security_group(context, id,
security_group))
name = security.get_nsgroup_name(updated_security_group)
description = updated_security_group['description']
try:
firewall.update_nsgroup(nsgroup_id, name, description)
firewall.update_section(section_id, name, description)
except nsx_exc.ManagerError:
with excutils.save_and_reraise_exception():
LOG.exception(_LE("Failed to update security-group %(name)s "
"(%(id)s), rolling back changes in "
"Neutron."), original_security_group)
super(NsxV3Plugin, self).update_security_group(
context, id, {'security_group': original_security_group})
return updated_security_group
def delete_security_group(self, context, id):
nsgroup_id, section_id = security.get_sg_mappings(context.session, id)
super(NsxV3Plugin, self).delete_security_group(context, id)
firewall.delete_section(section_id)
firewall.delete_nsgroup(nsgroup_id)
def create_security_group_rule(self, context, security_group_rule):
bulk_rule = {'security_group_rules': [security_group_rule]}
return self.create_security_group_rule_bulk(context, bulk_rule)[0]
def create_security_group_rule_bulk(self, context, security_group_rules):
security_group_rules_db = (
super(NsxV3Plugin, self).create_security_group_rule_bulk_native(
context, security_group_rules))
sg_id = security_group_rules_db[0]['security_group_id']
nsgroup_id, section_id = security.get_sg_mappings(context.session,
sg_id)
try:
rules = security.create_firewall_rules(
context, section_id, nsgroup_id, security_group_rules_db)
except nsx_exc.ManagerError:
with excutils.save_and_reraise_exception():
for rule in security_group_rules_db:
super(NsxV3Plugin, self).delete_security_group_rule(
context, rule['id'])
security.save_sg_rule_mappings(context.session, rules['rules'])
return security_group_rules_db
def delete_security_group_rule(self, context, id):
rule_db = self._get_security_group_rule(context, id)
sg_id = rule_db['security_group_id']
_, section_id = security.get_sg_mappings(context.session, sg_id)
fw_rule_id = security.get_sg_rule_mapping(context.session, id)
super(NsxV3Plugin, self).delete_security_group_rule(context, id)
firewall.delete_rule(section_id, fw_rule_id)

View File

@ -193,3 +193,26 @@ def get_logical_router(lrouter_uuid):
"id": lrouter_uuid,
"edge_cluster_uuid": uuidutils.generate_uuid()}
return FAKE_LROUTER
def add_rules_in_section(rules, section_id):
for rule in rules:
rule['id'] = uuidutils.generate_uuid()
return {'rules': rules}
def get_resource(resource):
return {'id': resource.split('/')[-1]}
def create_resource(resource, data):
data['id'] = uuidutils.generate_uuid()
return data
def update_resource(resource, data):
return resource
def delete_resource(resource):
pass

View File

@ -20,6 +20,7 @@ import neutron.tests.unit.db.test_db_base_plugin_v2 as test_plugin
from neutron.tests.unit.extensions import test_extra_dhcp_opt as test_dhcpopts
import neutron.tests.unit.extensions.test_securitygroup as ext_sg
from vmware_nsx.neutron.plugins.vmware.nsxlib import v3 as nsxlib
from vmware_nsx.neutron.plugins.vmware.nsxlib.v3 import dfw_api as firewall
from vmware_nsx.neutron.tests.unit.vmware import nsx_v3_mocks
PLUGIN_NAME = ('vmware_nsx.neutron.plugins.vmware.'
@ -49,6 +50,11 @@ class NsxPluginV3TestCase(test_plugin.NeutronDbPluginV2TestCase):
# TODO(berlin): fill valid data
nsxlib.get_edge_cluster = nsx_v3_mocks.get_edge_cluster
nsxlib.get_logical_router = nsx_v3_mocks.get_logical_router
firewall.add_rules_in_section = nsx_v3_mocks.add_rules_in_section
firewall.nsclient.create_resource = nsx_v3_mocks.create_resource
firewall.nsclient.update_resource = nsx_v3_mocks.update_resource
firewall.nsclient.get_resource = nsx_v3_mocks.get_resource
firewall.nsclient.delete_resource = nsx_v3_mocks.delete_resource
class TestNetworksV2(test_plugin.TestNetworksV2, NsxPluginV3TestCase):
@ -64,14 +70,20 @@ class SecurityGroupsTestCase(ext_sg.SecurityGroupDBTestCase):
def setUp(self,
plugin=PLUGIN_NAME,
ext_mgr=None):
super(SecurityGroupsTestCase, self).setUp(plugin=PLUGIN_NAME,
ext_mgr=ext_mgr)
nsxlib.create_logical_switch = nsx_v3_mocks.create_logical_switch
nsxlib.create_logical_port = nsx_v3_mocks.create_logical_port
nsxlib.update_logical_port = nsx_v3_mocks.update_logical_port
nsxlib.delete_logical_port = mock.Mock()
nsxlib.delete_logical_switch = mock.Mock()
super(SecurityGroupsTestCase, self).setUp(plugin=PLUGIN_NAME,
ext_mgr=ext_mgr)
nsxlib.get_logical_port = nsx_v3_mocks.get_logical_port
nsxlib.update_logical_port = nsx_v3_mocks.update_logical_port
firewall.add_rules_in_section = nsx_v3_mocks.add_rules_in_section
firewall.nsclient.create_resource = nsx_v3_mocks.create_resource
firewall.nsclient.update_resource = nsx_v3_mocks.update_resource
firewall.nsclient.get_resource = nsx_v3_mocks.get_resource
firewall.nsclient.delete_resource = nsx_v3_mocks.delete_resource
class TestSecurityGroups(ext_sg.TestSecurityGroups, SecurityGroupsTestCase):