You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
279 lines
12 KiB
279 lines
12 KiB
# Copyright (c) 2012 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. |
|
|
|
from neutron_lib.api.definitions import network as net_def |
|
from neutron_lib.api.definitions import port as port_def |
|
from neutron_lib.api.definitions import subnet as subnet_def |
|
from neutron_lib.api.definitions import subnetpool as subnetpool_def |
|
from neutron_lib import constants |
|
from neutron_lib.db import constants as db_const |
|
from neutron_lib.db import model_base |
|
import sqlalchemy as sa |
|
from sqlalchemy import orm |
|
from sqlalchemy import sql |
|
|
|
from neutron.db.network_dhcp_agent_binding import models as ndab_model |
|
from neutron.db import rbac_db_models |
|
from neutron.db import standard_attr |
|
|
|
|
|
class IPAllocationPool(model_base.BASEV2, model_base.HasId): |
|
"""Representation of an allocation pool in a Neutron subnet.""" |
|
|
|
subnet_id = sa.Column(sa.String(36), sa.ForeignKey('subnets.id', |
|
ondelete="CASCADE"), |
|
nullable=True) |
|
first_ip = sa.Column(sa.String(64), nullable=False) |
|
last_ip = sa.Column(sa.String(64), nullable=False) |
|
|
|
def __repr__(self): |
|
return "%s - %s" % (self.first_ip, self.last_ip) |
|
|
|
|
|
class IPAllocation(model_base.BASEV2): |
|
"""Internal representation of allocated IP addresses in a Neutron subnet. |
|
""" |
|
|
|
port_id = sa.Column(sa.String(36), sa.ForeignKey('ports.id', |
|
ondelete="CASCADE"), |
|
nullable=True) |
|
ip_address = sa.Column(sa.String(64), nullable=False, primary_key=True) |
|
subnet_id = sa.Column(sa.String(36), sa.ForeignKey('subnets.id', |
|
ondelete="CASCADE"), |
|
nullable=False, primary_key=True) |
|
network_id = sa.Column(sa.String(36), sa.ForeignKey("networks.id", |
|
ondelete="CASCADE"), |
|
nullable=False, primary_key=True) |
|
revises_on_change = ('port', ) |
|
|
|
|
|
class Route(object): |
|
"""mixin of a route.""" |
|
|
|
destination = sa.Column(sa.String(64), nullable=False, primary_key=True) |
|
nexthop = sa.Column(sa.String(64), nullable=False, primary_key=True) |
|
|
|
|
|
class SubnetRoute(model_base.BASEV2, Route): |
|
|
|
subnet_id = sa.Column(sa.String(36), |
|
sa.ForeignKey('subnets.id', |
|
ondelete="CASCADE"), |
|
primary_key=True) |
|
|
|
|
|
class Port(standard_attr.HasStandardAttributes, model_base.BASEV2, |
|
model_base.HasId, model_base.HasProject): |
|
"""Represents a port on a Neutron v2 network.""" |
|
|
|
name = sa.Column(sa.String(db_const.NAME_FIELD_SIZE)) |
|
network_id = sa.Column(sa.String(36), sa.ForeignKey("networks.id"), |
|
nullable=False) |
|
fixed_ips = orm.relationship(IPAllocation, |
|
backref=orm.backref('port', |
|
load_on_pending=True), |
|
lazy='subquery', |
|
cascade='all, delete-orphan', |
|
order_by=(IPAllocation.ip_address, |
|
IPAllocation.subnet_id)) |
|
|
|
mac_address = sa.Column(sa.String(32), nullable=False) |
|
admin_state_up = sa.Column(sa.Boolean(), nullable=False) |
|
status = sa.Column(sa.String(16), nullable=False) |
|
device_id = sa.Column(sa.String(db_const.DEVICE_ID_FIELD_SIZE), |
|
nullable=False) |
|
device_owner = sa.Column(sa.String(db_const.DEVICE_OWNER_FIELD_SIZE), |
|
nullable=False) |
|
ip_allocation = sa.Column(sa.String(16)) |
|
|
|
__table_args__ = ( |
|
sa.Index( |
|
'ix_ports_network_id_mac_address', 'network_id', 'mac_address'), |
|
sa.Index( |
|
'ix_ports_network_id_device_owner', 'network_id', 'device_owner'), |
|
sa.Index('ix_ports_device_id', 'device_id'), |
|
sa.UniqueConstraint( |
|
network_id, mac_address, |
|
name='uniq_ports0network_id0mac_address'), |
|
model_base.BASEV2.__table_args__ |
|
) |
|
api_collections = [port_def.COLLECTION_NAME] |
|
collection_resource_map = {port_def.COLLECTION_NAME: |
|
port_def.RESOURCE_NAME} |
|
tag_support = True |
|
|
|
def __init__(self, id=None, tenant_id=None, project_id=None, name=None, |
|
network_id=None, mac_address=None, admin_state_up=None, |
|
status=None, device_id=None, device_owner=None, |
|
fixed_ips=None, **kwargs): |
|
super(Port, self).__init__(**kwargs) |
|
self.id = id |
|
self.project_id = project_id or tenant_id |
|
self.name = name |
|
self.network_id = network_id |
|
self.mac_address = mac_address |
|
self.admin_state_up = admin_state_up |
|
self.device_owner = device_owner |
|
self.device_id = device_id |
|
# Since this is a relationship only set it if one is passed in. |
|
if fixed_ips: |
|
self.fixed_ips = fixed_ips |
|
|
|
# NOTE(arosen): status must be set last as an event is triggered on! |
|
self.status = status |
|
|
|
|
|
class DNSNameServer(model_base.BASEV2): |
|
"""Internal representation of a DNS nameserver.""" |
|
|
|
address = sa.Column(sa.String(128), nullable=False, primary_key=True) |
|
subnet_id = sa.Column(sa.String(36), |
|
sa.ForeignKey('subnets.id', |
|
ondelete="CASCADE"), |
|
primary_key=True) |
|
order = sa.Column(sa.Integer, nullable=False, server_default='0') |
|
|
|
|
|
class Subnet(standard_attr.HasStandardAttributes, model_base.BASEV2, |
|
model_base.HasId, model_base.HasProject): |
|
"""Represents a neutron subnet. |
|
|
|
When a subnet is created the first and last entries will be created. These |
|
are used for the IP allocation. |
|
""" |
|
|
|
name = sa.Column(sa.String(db_const.NAME_FIELD_SIZE)) |
|
network_id = sa.Column(sa.String(36), sa.ForeignKey('networks.id'), |
|
nullable=False) |
|
# Added by the segments service plugin |
|
segment_id = sa.Column(sa.String(36), sa.ForeignKey('networksegments.id')) |
|
subnetpool_id = sa.Column(sa.String(36), index=True) |
|
# NOTE: Explicitly specify join conditions for the relationship because |
|
# subnetpool_id in subnet might be 'prefix_delegation' when the IPv6 Prefix |
|
# Delegation is enabled |
|
subnetpool = orm.relationship( |
|
'SubnetPool', lazy='joined', |
|
foreign_keys='Subnet.subnetpool_id', |
|
primaryjoin='Subnet.subnetpool_id==SubnetPool.id') |
|
ip_version = sa.Column(sa.Integer, nullable=False) |
|
cidr = sa.Column(sa.String(64), nullable=False) |
|
gateway_ip = sa.Column(sa.String(64)) |
|
network_standard_attr = orm.relationship( |
|
'StandardAttribute', lazy='subquery', viewonly=True, |
|
secondary='networks', uselist=False, |
|
load_on_pending=True) |
|
revises_on_change = ('network_standard_attr', ) |
|
allocation_pools = orm.relationship(IPAllocationPool, |
|
backref='subnet', |
|
lazy="subquery", |
|
cascade='delete') |
|
enable_dhcp = sa.Column(sa.Boolean()) |
|
dns_nameservers = orm.relationship(DNSNameServer, |
|
backref='subnet', |
|
cascade='all, delete, delete-orphan', |
|
order_by=DNSNameServer.order, |
|
lazy='subquery') |
|
routes = orm.relationship(SubnetRoute, |
|
backref='subnet', |
|
cascade='all, delete, delete-orphan', |
|
lazy='subquery') |
|
ipv6_ra_mode = sa.Column(sa.Enum(constants.IPV6_SLAAC, |
|
constants.DHCPV6_STATEFUL, |
|
constants.DHCPV6_STATELESS, |
|
name='ipv6_ra_modes'), |
|
nullable=True) |
|
ipv6_address_mode = sa.Column(sa.Enum(constants.IPV6_SLAAC, |
|
constants.DHCPV6_STATEFUL, |
|
constants.DHCPV6_STATELESS, |
|
name='ipv6_address_modes'), |
|
nullable=True) |
|
# subnets don't have their own rbac_entries, they just inherit from |
|
# the network rbac entries |
|
rbac_entries = orm.relationship( |
|
rbac_db_models.NetworkRBAC, lazy='subquery', uselist=True, |
|
foreign_keys='Subnet.network_id', |
|
primaryjoin='Subnet.network_id==NetworkRBAC.object_id') |
|
api_collections = [subnet_def.COLLECTION_NAME] |
|
collection_resource_map = {subnet_def.COLLECTION_NAME: |
|
subnet_def.RESOURCE_NAME} |
|
tag_support = True |
|
|
|
|
|
class SubnetPoolPrefix(model_base.BASEV2): |
|
"""Represents a neutron subnet pool prefix |
|
""" |
|
|
|
__tablename__ = 'subnetpoolprefixes' |
|
|
|
cidr = sa.Column(sa.String(64), nullable=False, primary_key=True) |
|
subnetpool_id = sa.Column(sa.String(36), |
|
sa.ForeignKey('subnetpools.id', |
|
ondelete='CASCADE'), |
|
nullable=False, |
|
primary_key=True) |
|
|
|
|
|
class SubnetPool(standard_attr.HasStandardAttributes, model_base.BASEV2, |
|
model_base.HasId, model_base.HasProject): |
|
"""Represents a neutron subnet pool. |
|
""" |
|
|
|
name = sa.Column(sa.String(db_const.NAME_FIELD_SIZE)) |
|
ip_version = sa.Column(sa.Integer, nullable=False) |
|
default_prefixlen = sa.Column(sa.Integer, nullable=False) |
|
min_prefixlen = sa.Column(sa.Integer, nullable=False) |
|
max_prefixlen = sa.Column(sa.Integer, nullable=False) |
|
shared = sa.Column(sa.Boolean, nullable=False) |
|
is_default = sa.Column(sa.Boolean, nullable=False, |
|
server_default=sql.false()) |
|
default_quota = sa.Column(sa.Integer, nullable=True) |
|
hash = sa.Column(sa.String(36), nullable=False, server_default='') |
|
address_scope_id = sa.Column(sa.String(36), nullable=True) |
|
prefixes = orm.relationship(SubnetPoolPrefix, |
|
backref='subnetpools', |
|
cascade='all, delete, delete-orphan', |
|
lazy='subquery') |
|
api_collections = [subnetpool_def.COLLECTION_NAME] |
|
collection_resource_map = {subnetpool_def.COLLECTION_NAME: |
|
subnetpool_def.RESOURCE_NAME} |
|
tag_support = True |
|
|
|
|
|
class Network(standard_attr.HasStandardAttributes, model_base.BASEV2, |
|
model_base.HasId, model_base.HasProject): |
|
"""Represents a v2 neutron network.""" |
|
|
|
name = sa.Column(sa.String(db_const.NAME_FIELD_SIZE)) |
|
subnets = orm.relationship( |
|
Subnet, |
|
lazy="subquery") |
|
status = sa.Column(sa.String(16)) |
|
admin_state_up = sa.Column(sa.Boolean) |
|
vlan_transparent = sa.Column(sa.Boolean, nullable=True) |
|
rbac_entries = orm.relationship(rbac_db_models.NetworkRBAC, |
|
backref=orm.backref('network', |
|
load_on_pending=True), |
|
lazy='subquery', |
|
cascade='all, delete, delete-orphan') |
|
availability_zone_hints = sa.Column(sa.String(255)) |
|
# TODO(ihrachys) provide data migration path to fill in mtus for existing |
|
# networks in Queens when all controllers run Pike+ code |
|
mtu = sa.Column(sa.Integer, nullable=True) |
|
dhcp_agents = orm.relationship( |
|
'Agent', lazy='subquery', viewonly=True, |
|
secondary=ndab_model.NetworkDhcpAgentBinding.__table__) |
|
api_collections = [net_def.COLLECTION_NAME] |
|
collection_resource_map = {net_def.COLLECTION_NAME: net_def.RESOURCE_NAME} |
|
tag_support = True
|
|
|