From 93bf7a02d4ece28bdfb88c852b8557a50017361d Mon Sep 17 00:00:00 2001 From: Kobi Samoray Date: Thu, 25 Dec 2014 12:06:16 +0200 Subject: [PATCH] VMWare-NSXv: VMWare NSXv database models For Kilo, the vendor-specific code should be moved to stackforge repo, excluding the database models (https://review.openstack.org/#/c/134680/). This patch adds the database model for VMWare NSXv plugin from stackforge/vmware-nsx repo. Partially-Implements: blueprint vmware-nsx-v Change-Id: I17cbc1ba59131bd3bdefa232800842a9e739945f --- .../versions/4dbe243cd84d_nsxv.py | 166 +++++++++++++ .../alembic_migrations/versions/HEAD | 2 +- neutron/db/migration/models/head.py | 1 + .../plugins/vmware/common/nsxv_constants.py | 28 +++ neutron/plugins/vmware/dbexts/nsxv_models.py | 235 ++++++++++++++++++ 5 files changed, 431 insertions(+), 1 deletion(-) create mode 100644 neutron/db/migration/alembic_migrations/versions/4dbe243cd84d_nsxv.py create mode 100644 neutron/plugins/vmware/common/nsxv_constants.py create mode 100644 neutron/plugins/vmware/dbexts/nsxv_models.py diff --git a/neutron/db/migration/alembic_migrations/versions/4dbe243cd84d_nsxv.py b/neutron/db/migration/alembic_migrations/versions/4dbe243cd84d_nsxv.py new file mode 100644 index 000000000..5867f6c9c --- /dev/null +++ b/neutron/db/migration/alembic_migrations/versions/4dbe243cd84d_nsxv.py @@ -0,0 +1,166 @@ +# 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. +# + +"""nsxv + +Revision ID: 4dbe243cd84d +Revises: 38495dc99731 +Create Date: 2015-01-05 23:22:04.501609 + +""" + +# revision identifiers, used by Alembic. +revision = '4dbe243cd84d' +down_revision = '38495dc99731' +from alembic import op +import sqlalchemy as sa + + +appliance_sizes_enum = sa.Enum('compact', 'large', 'xlarge', 'quadlarge', + name='nsxv_router_bindings_appliance_size') +edge_types_enum = sa.Enum('service', 'vdr', + name='nsxv_router_bindings_edge_type') +internal_network_purpose_enum = sa.Enum('inter_edge_net', + name='nsxv_internal_networks_purpose') +internal_edge_purpose_enum = sa.Enum('inter_edge_net', + name='nsxv_internal_edges_purpose') +tz_binding_type_enum = sa.Enum('flat', 'vlan', 'portgroup', + name='nsxv_tz_network_bindings_binding_type') + + +def upgrade(): + op.create_table( + 'nsxv_router_bindings', + sa.Column('status', sa.String(length=16), nullable=False), + sa.Column('status_description', sa.String(length=255), nullable=True), + sa.Column('router_id', sa.String(length=36), nullable=False), + sa.Column('edge_id', sa.String(length=36), nullable=True), + sa.Column('lswitch_id', sa.String(length=36), nullable=True), + sa.Column('appliance_size', + appliance_sizes_enum, + nullable=True), + sa.Column('edge_type', edge_types_enum, nullable=True), + sa.PrimaryKeyConstraint('router_id')) + op.create_table( + 'nsxv_internal_networks', + sa.Column('network_purpose', internal_network_purpose_enum, + nullable=False), + sa.Column('network_id', sa.String(length=36), nullable=False), + sa.ForeignKeyConstraint(['network_id'], ['networks.id'], + ondelete='CASCADE'), + sa.PrimaryKeyConstraint('network_purpose')) + op.create_table( + 'nsxv_internal_edges', + sa.Column('ext_ip_address', sa.String(length=64), nullable=False), + sa.Column('router_id', sa.String(length=36), nullable=False), + sa.Column('purpose', internal_edge_purpose_enum, nullable=True), + sa.PrimaryKeyConstraint('ext_ip_address')) + op.create_table( + 'nsxv_firewall_rule_bindings', + sa.Column('rule_id', sa.String(length=36), nullable=False), + sa.Column('edge_id', sa.String(length=36), nullable=False), + sa.Column('rule_vse_id', sa.String(length=36), nullable=True), + sa.PrimaryKeyConstraint('rule_id', 'edge_id')) + op.create_table( + 'nsxv_edge_dhcp_static_bindings', + sa.Column('edge_id', sa.String(length=36), nullable=False), + sa.Column('mac_address', sa.String(length=32), nullable=False), + sa.Column('binding_id', sa.String(length=36), nullable=False), + sa.PrimaryKeyConstraint('edge_id', 'mac_address')) + op.create_table( + 'nsxv_edge_vnic_bindings', + sa.Column('edge_id', sa.String(length=36), nullable=False), + sa.Column('vnic_index', sa.Integer(), nullable=False), + sa.Column('tunnel_index', sa.Integer(), nullable=False), + sa.Column('network_id', sa.String(length=36), nullable=True), + sa.PrimaryKeyConstraint('edge_id', 'vnic_index', 'tunnel_index')) + op.create_table( + 'nsxv_spoofguard_policy_network_mappings', + sa.Column('network_id', sa.String(length=36), nullable=False), + sa.Column('policy_id', sa.String(length=36), nullable=False), + sa.ForeignKeyConstraint(['network_id'], ['networks.id'], + ondelete='CASCADE'), + sa.PrimaryKeyConstraint('network_id')) + op.create_table( + 'nsxv_security_group_section_mappings', + sa.Column('neutron_id', sa.String(length=36), nullable=False), + sa.Column('ip_section_id', sa.String(length=100), nullable=True), + sa.ForeignKeyConstraint(['neutron_id'], ['securitygroups.id'], + ondelete='CASCADE'), + sa.PrimaryKeyConstraint('neutron_id')) + op.create_table( + 'nsxv_tz_network_bindings', + sa.Column('network_id', sa.String(length=36), nullable=False), + sa.Column('binding_type', + tz_binding_type_enum, + nullable=False), + sa.Column('phy_uuid', sa.String(length=36), nullable=True), + sa.Column('vlan_id', sa.Integer(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint(['network_id'], ['networks.id'], + ondelete='CASCADE'), + sa.PrimaryKeyConstraint('network_id', 'binding_type', 'phy_uuid', + 'vlan_id')) + op.create_table( + 'nsxv_port_vnic_mappings', + sa.Column('neutron_id', sa.String(length=36), nullable=False), + sa.Column('nsx_id', sa.String(length=42), nullable=False), + sa.ForeignKeyConstraint(['neutron_id'], ['ports.id'], + ondelete='CASCADE'), + sa.PrimaryKeyConstraint('neutron_id', 'nsx_id')) + op.create_table( + 'nsxv_port_index_mappings', + sa.Column('port_id', sa.String(length=36), nullable=False), + sa.Column('device_id', sa.String(length=255), nullable=False), + sa.Column('index', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['port_id'], ['ports.id'], ondelete='CASCADE'), + sa.PrimaryKeyConstraint('port_id'), + sa.UniqueConstraint('device_id', 'index')) + op.create_table( + 'nsxv_rule_mappings', + sa.Column('neutron_id', sa.String(length=36), nullable=False), + sa.Column('nsx_rule_id', sa.String(length=36), nullable=False), + sa.ForeignKeyConstraint(['neutron_id'], ['securitygrouprules.id'], + ondelete='CASCADE'), + sa.PrimaryKeyConstraint('neutron_id', 'nsx_rule_id')) + op.create_table( + 'nsxv_router_ext_attributes', + sa.Column('router_id', sa.String(length=36), nullable=False), + sa.Column('distributed', sa.Boolean(), nullable=False), + sa.Column('exclusive', sa.Boolean(), nullable=False), + sa.Column('service_router', sa.Boolean(), nullable=False), + sa.ForeignKeyConstraint(['router_id'], ['routers.id'], + ondelete='CASCADE'), + sa.PrimaryKeyConstraint('router_id')) + + +def downgrade(): + op.drop_table('nsxv_router_ext_attributes') + op.drop_table('nsxv_rule_mappings') + op.drop_table('nsxv_port_index_mappings') + op.drop_table('nsxv_port_vnic_mappings') + op.drop_table('nsxv_tz_network_bindings') + op.drop_table('nsxv_section_mappings') + op.drop_table('nsxv_spoofguard_policy_network_mappings') + op.drop_table('nsxv_edge_vnic_bindings') + op.drop_table('nsxv_edge_dhcp_static_bindings') + op.drop_table('nsxv_firewall_rule_bindings') + op.drop_table('nsxv_internal_edges') + op.drop_table('nsxv_internal_networks') + op.drop_table('nsxv_router_bindings') + appliance_sizes_enum.drop(op.get_bind(), checkfirst=False) + edge_types_enum.drop(op.get_bind(), checkfirst=False) + internal_network_purpose_enum.drop(op.get_bind(), checkfirst=False) + internal_edge_purpose_enum.drop(op.get_bind(), checkfirst=False) + tz_binding_type_enum.drop(op.get_bind(), checkfirst=False) \ No newline at end of file diff --git a/neutron/db/migration/alembic_migrations/versions/HEAD b/neutron/db/migration/alembic_migrations/versions/HEAD index f7415c8a2..a3793d94d 100644 --- a/neutron/db/migration/alembic_migrations/versions/HEAD +++ b/neutron/db/migration/alembic_migrations/versions/HEAD @@ -1 +1 @@ -38495dc99731 \ No newline at end of file +4dbe243cd84d diff --git a/neutron/db/migration/models/head.py b/neutron/db/migration/models/head.py index 43222e477..7c46b8b5f 100644 --- a/neutron/db/migration/models/head.py +++ b/neutron/db/migration/models/head.py @@ -71,6 +71,7 @@ from neutron.plugins.vmware.dbexts import lsn_db # noqa from neutron.plugins.vmware.dbexts import maclearning # noqa from neutron.plugins.vmware.dbexts import models as vmware_models # noqa from neutron.plugins.vmware.dbexts import networkgw_db # noqa +from neutron.plugins.vmware.dbexts import nsxv_models # noqa from neutron.plugins.vmware.dbexts import qos_db # noqa from neutron.plugins.vmware.dbexts import vcns_models # noqa diff --git a/neutron/plugins/vmware/common/nsxv_constants.py b/neutron/plugins/vmware/common/nsxv_constants.py new file mode 100644 index 000000000..3d1ae85f3 --- /dev/null +++ b/neutron/plugins/vmware/common/nsxv_constants.py @@ -0,0 +1,28 @@ +# Copyright 2015 VMware, Inc. +# 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. + +# Edge size +COMPACT = 'compact' +LARGE = 'large' +XLARGE = 'xlarge' +QUADLARGE = 'quadlarge' + + +# Edge type +SERVICE_EDGE = 'service' +VDR_EDGE = 'vdr' + +# Internal element purpose +INTER_EDGE_PURPOSE = 'inter_edge_net' diff --git a/neutron/plugins/vmware/dbexts/nsxv_models.py b/neutron/plugins/vmware/dbexts/nsxv_models.py new file mode 100644 index 000000000..4e9cecd95 --- /dev/null +++ b/neutron/plugins/vmware/dbexts/nsxv_models.py @@ -0,0 +1,235 @@ +# Copyright 2015 VMware, Inc. +# +# 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. + + +import sqlalchemy as sa +from sqlalchemy import orm + +from neutron.db import l3_db +from neutron.db import model_base +from neutron.db import models_v2 +from neutron.plugins.vmware.common import nsxv_constants + + +class NsxvRouterBinding(model_base.BASEV2, models_v2.HasStatusDescription): + """Represents the mapping between neutron router and vShield Edge.""" + + __tablename__ = 'nsxv_router_bindings' + + # no ForeignKey to routers.id because for now, a router can be removed + # from routers when delete_router is executed, but the binding is only + # removed after the Edge is deleted + router_id = sa.Column(sa.String(36), + primary_key=True) + edge_id = sa.Column(sa.String(36), + nullable=True) + lswitch_id = sa.Column(sa.String(36), + nullable=True) + appliance_size = sa.Column(sa.Enum( + nsxv_constants.COMPACT, + nsxv_constants.LARGE, + nsxv_constants.XLARGE, + nsxv_constants.QUADLARGE, + name='nsxv_router_bindings_appliance_size')) + edge_type = sa.Column(sa.Enum(nsxv_constants.SERVICE_EDGE, + nsxv_constants.VDR_EDGE, + name='nsxv_router_bindings_edge_type')) + + +class NsxvEdgeVnicBinding(model_base.BASEV2): + """Represents mapping between vShield Edge vnic and neutron netowrk.""" + + __tablename__ = 'nsxv_edge_vnic_bindings' + + edge_id = sa.Column(sa.String(36), + primary_key=True) + vnic_index = sa.Column(sa.Integer(), + primary_key=True) + tunnel_index = sa.Column(sa.Integer(), + primary_key=True) + network_id = sa.Column(sa.String(36), nullable=True) + + +class NsxvEdgeDhcpStaticBinding(model_base.BASEV2): + """Represents mapping between mac addr and bindingId.""" + + __tablename__ = 'nsxv_edge_dhcp_static_bindings' + + edge_id = sa.Column(sa.String(36), primary_key=True) + mac_address = sa.Column(sa.String(32), primary_key=True) + binding_id = sa.Column(sa.String(36), nullable=False) + + +class NsxvInternalNetworks(model_base.BASEV2): + """Represents internal networks between NSXV plugin elements.""" + + __tablename__ = 'nsxv_internal_networks' + + network_purpose = sa.Column( + sa.Enum(nsxv_constants.INTER_EDGE_PURPOSE, + name='nsxv_internal_networks_purpose'), + primary_key=True) + network_id = sa.Column(sa.String(36), + sa.ForeignKey("networks.id", ondelete="CASCADE"), + nullable=False) + + +class NsxvInternalEdges(model_base.BASEV2): + """Represents internal Edge appliances for NSXV plugin operations.""" + + __tablename__ = 'nsxv_internal_edges' + + ext_ip_address = sa.Column(sa.String(64), primary_key=True) + router_id = sa.Column(sa.String(36), nullable=False) + purpose = sa.Column( + sa.Enum(nsxv_constants.INTER_EDGE_PURPOSE, + name='nsxv_internal_edges_purpose')) + + +class NsxvSecurityGroupSectionMapping(model_base.BASEV2): + """Backend mappings for Neutron Rule Sections. + + This class maps a neutron security group identifier to the corresponding + NSX layer 3 section. + """ + + __tablename__ = 'nsxv_security_group_section_mappings' + neutron_id = sa.Column(sa.String(36), + sa.ForeignKey('securitygroups.id', + ondelete="CASCADE"), + primary_key=True) + ip_section_id = sa.Column(sa.String(100)) + + +class NsxvRuleMapping(model_base.BASEV2): + """Backend mappings for Neutron Rule Sections. + + This class maps a neutron security group identifier to the corresponding + NSX layer 3 and layer 2 sections. + """ + + __tablename__ = 'nsxv_rule_mappings' + + neutron_id = sa.Column(sa.String(36), + sa.ForeignKey('securitygrouprules.id', + ondelete="CASCADE"), + primary_key=True) + nsx_rule_id = sa.Column(sa.String(36), primary_key=True) + + +class NsxvPortVnicMapping(model_base.BASEV2): + """Maps neutron port to NSXv VM Vnic Id.""" + + __tablename__ = 'nsxv_port_vnic_mappings' + + neutron_id = sa.Column(sa.String(36), + sa.ForeignKey('ports.id', ondelete="CASCADE"), + primary_key=True) + nsx_id = sa.Column(sa.String(42), primary_key=True) + + +class NsxvRouterExtAttributes(model_base.BASEV2): + """Router attributes managed by NSX plugin extensions.""" + + __tablename__ = 'nsxv_router_ext_attributes' + + router_id = sa.Column(sa.String(36), + sa.ForeignKey('routers.id', ondelete="CASCADE"), + primary_key=True) + distributed = sa.Column(sa.Boolean, default=False, nullable=False) + exclusive = sa.Column(sa.Boolean, default=False, nullable=False) + service_router = sa.Column(sa.Boolean, default=False, nullable=False) + # Add a relationship to the Router model in order to instruct + # SQLAlchemy to eagerly load this association + router = orm.relationship( + l3_db.Router, + backref=orm.backref("nsx_attributes", lazy='joined', + uselist=False, cascade='delete')) + + +class NsxvTzNetworkBinding(model_base.BASEV2): + """Represents a binding of a virtual network with a transport zone. + + This model class associates a Neutron network with a transport zone; + optionally a vlan ID might be used if the binding type is 'bridge' + """ + + __tablename__ = 'nsxv_tz_network_bindings' + + network_id = sa.Column(sa.String(36), + sa.ForeignKey('networks.id', ondelete="CASCADE"), + primary_key=True) + binding_type = sa.Column(sa.Enum('flat', 'vlan', 'portgroup', + name='tz_network_bindings_binding_type'), + nullable=False, primary_key=True) + phy_uuid = sa.Column(sa.String(36), primary_key=True, nullable=True) + vlan_id = sa.Column(sa.Integer, primary_key=True, nullable=True, + autoincrement=False) + + def __init__(self, network_id, binding_type, phy_uuid, vlan_id): + self.network_id = network_id + self.binding_type = binding_type + self.phy_uuid = phy_uuid + self.vlan_id = vlan_id + + def __repr__(self): + return "" % (self.network_id, + self.binding_type, + self.phy_uuid, + self.vlan_id) + + +class NsxvPortIndexMapping(model_base.BASEV2): + """Associates attached Neutron ports with the instance VNic index.""" + + __tablename__ = 'nsxv_port_index_mappings' + + port_id = sa.Column(sa.String(36), + sa.ForeignKey('ports.id', ondelete="CASCADE"), + primary_key=True) + device_id = sa.Column(sa.String(255), nullable=False) + index = sa.Column(sa.Integer, nullable=False) + __table_args__ = (sa.UniqueConstraint(device_id, index),) + + # Add a relationship to the Port model in order to instruct SQLAlchemy to + # eagerly read port vnic-index + port = orm.relationship( + models_v2.Port, + backref=orm.backref("vnic_index", lazy='joined', + uselist=False, cascade='delete')) + + +class NsxvEdgeFirewallRuleBinding(model_base.BASEV2): + """Mapping between firewall rule and edge firewall rule_id.""" + + __tablename__ = 'nsxv_firewall_rule_bindings' + + rule_id = sa.Column(sa.String(36), + primary_key=True) + edge_id = sa.Column(sa.String(36), primary_key=True) + rule_vse_id = sa.Column(sa.String(36)) + + +class NsxvSpoofGuardPolicyNetworkMapping(model_base.BASEV2): + """Mapping between SpoofGuard and neutron networks""" + + __tablename__ = 'nsxv_spoofguard_policy_network_mappings' + + network_id = sa.Column(sa.String(36), + sa.ForeignKey('networks.id', ondelete='CASCADE'), + primary_key=True, + nullable=False) + policy_id = sa.Column(sa.String(36), nullable=False) -- 2.45.2