Add name and desc to networksegments table
This patch adds the name and description column to the networksegments table. Change-Id: I7edc224e25e604dfd7613b945a4ca16d9e385760 Partially-Implements: blueprint routed-networks
This commit is contained in:
parent
0eec50b12f
commit
5ef869b3bc
|
@ -1 +1 @@
|
|||
b12a3ef66e62
|
||||
97c25b0d2353
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
# Copyright 2016 NEC Technologies Limited
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""Add Name and Description to the networksegments table """
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '97c25b0d2353'
|
||||
down_revision = 'b12a3ef66e62'
|
||||
depends_on = ('89ab9a816d70',)
|
||||
|
||||
# As this script depends on another migration which was a contract script,
|
||||
# therefore the following column addition ( which should have been in an
|
||||
# expand phase ) is also submitted in the contract phase. For information
|
||||
# about the expand and contract scripts and how the depends_on works, please
|
||||
# refer <http://docs.openstack.org/developer/neutron/devref/
|
||||
# alembic_migrations.html#expand-and-contract-scripts>
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
TBL = 'networksegments'
|
||||
|
||||
TBL_MODEL = sa.Table(TBL, sa.MetaData(),
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('standard_attr_id', sa.BigInteger(),
|
||||
nullable=True))
|
||||
|
||||
|
||||
standardattrs = sa.Table(
|
||||
'standardattributes', sa.MetaData(),
|
||||
sa.Column('id', sa.BigInteger(), primary_key=True, autoincrement=True),
|
||||
sa.Column('resource_type', sa.String(length=255), nullable=False))
|
||||
|
||||
|
||||
def update_existing_records():
|
||||
session = sa.orm.Session(bind=op.get_bind())
|
||||
values = []
|
||||
with session.begin(subtransactions=True):
|
||||
for row in session.query(TBL_MODEL):
|
||||
# NOTE from kevinbenton: without this disabled, pylint complains
|
||||
# about a missing 'dml' argument.
|
||||
#pylint: disable=no-value-for-parameter
|
||||
res = session.execute(
|
||||
standardattrs.insert().values(resource_type=TBL)
|
||||
)
|
||||
session.execute(
|
||||
TBL_MODEL.update().values(
|
||||
standard_attr_id=res.inserted_primary_key).where(
|
||||
TBL_MODEL.c.id == row[0])
|
||||
)
|
||||
# this commit is necessary to allow further operations
|
||||
session.commit()
|
||||
return values
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.add_column(TBL, sa.Column('standard_attr_id', sa.BigInteger(),
|
||||
nullable=True))
|
||||
op.add_column(TBL,
|
||||
sa.Column('name', sa.String(255),
|
||||
nullable=True))
|
||||
update_existing_records()
|
||||
# add the constraint now that everything is populated on that table
|
||||
op.create_foreign_key(
|
||||
constraint_name=None, source_table=TBL,
|
||||
referent_table='standardattributes',
|
||||
local_cols=['standard_attr_id'], remote_cols=['id'],
|
||||
ondelete='CASCADE')
|
||||
op.alter_column(TBL, 'standard_attr_id', nullable=False,
|
||||
existing_type=sa.BigInteger(), existing_nullable=True,
|
||||
existing_server_default=False)
|
||||
op.create_unique_constraint(
|
||||
constraint_name='uniq_%s0standard_attr_id' % TBL,
|
||||
table_name=TBL, columns=['standard_attr_id'])
|
||||
|
||||
|
||||
def contract_creation_exceptions():
|
||||
"""
|
||||
Return create exceptions.
|
||||
|
||||
These elements depend on the networksegments table which are added
|
||||
in the contract branch.
|
||||
"""
|
||||
return {
|
||||
sa.Column: ['networksegments.name',
|
||||
'networksegments.standard_attr_id'],
|
||||
}
|
|
@ -17,9 +17,11 @@ import sqlalchemy as sa
|
|||
from sqlalchemy.orm import exc
|
||||
|
||||
from neutron._i18n import _LI
|
||||
from neutron.api.v2 import attributes
|
||||
from neutron.callbacks import events
|
||||
from neutron.callbacks import registry
|
||||
from neutron.callbacks import resources
|
||||
from neutron.db import standard_attr
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
@ -31,7 +33,8 @@ but in Mitaka the ML2 NetworkSegment table was promoted here.
|
|||
"""
|
||||
|
||||
|
||||
class NetworkSegment(model_base.BASEV2, model_base.HasId):
|
||||
class NetworkSegment(standard_attr.HasStandardAttributes,
|
||||
model_base.BASEV2, model_base.HasId):
|
||||
"""Represent persistent state of a network segment.
|
||||
|
||||
A network segment is a portion of a neutron network with a
|
||||
|
@ -48,6 +51,8 @@ class NetworkSegment(model_base.BASEV2, model_base.HasId):
|
|||
is_dynamic = sa.Column(sa.Boolean, default=False, nullable=False,
|
||||
server_default=sa.sql.false())
|
||||
segment_index = sa.Column(sa.Integer, nullable=False, server_default='0')
|
||||
name = sa.Column(sa.String(attributes.NAME_MAX_LEN),
|
||||
nullable=True)
|
||||
|
||||
|
||||
NETWORK_TYPE = NetworkSegment.network_type.name
|
||||
|
|
|
@ -31,6 +31,8 @@ SEGMENT_ID = 'segment_id'
|
|||
NETWORK_TYPE = 'network_type'
|
||||
PHYSICAL_NETWORK = 'physical_network'
|
||||
SEGMENTATION_ID = 'segmentation_id'
|
||||
NAME_LEN = attributes.NAME_MAX_LEN
|
||||
DESC_LEN = attributes.DESCRIPTION_MAX_LEN
|
||||
|
||||
# Attribute Map
|
||||
RESOURCE_ATTRIBUTE_MAP = {
|
||||
|
@ -65,6 +67,16 @@ RESOURCE_ATTRIBUTE_MAP = {
|
|||
'default': constants.ATTR_NOT_SPECIFIED,
|
||||
'convert_to': converters.convert_to_int,
|
||||
'is_visible': True},
|
||||
'name': {'allow_post': True,
|
||||
'allow_put': True,
|
||||
'default': constants.ATTR_NOT_SPECIFIED,
|
||||
'validate': {'type:string_or_none': NAME_LEN},
|
||||
'is_visible': True},
|
||||
'description': {'allow_post': True,
|
||||
'allow_put': True,
|
||||
'default': constants.ATTR_NOT_SPECIFIED,
|
||||
'validate': {'type:string_or_none': DESC_LEN},
|
||||
'is_visible': True},
|
||||
},
|
||||
attributes.SUBNETS: {
|
||||
SEGMENT_ID: {'allow_post': True,
|
||||
|
|
|
@ -27,6 +27,7 @@ class NetworkSegment(base.NeutronDbObject):
|
|||
fields = {
|
||||
'id': obj_fields.UUIDField(),
|
||||
'network_id': obj_fields.UUIDField(),
|
||||
'name': obj_fields.StringField(),
|
||||
'network_type': obj_fields.StringField(),
|
||||
'physical_network': obj_fields.StringField(nullable=True),
|
||||
'segmentation_id': obj_fields.IntegerField(nullable=True),
|
||||
|
|
|
@ -65,6 +65,8 @@ class SegmentDbMixin(common_db_mixin.CommonDbMixin):
|
|||
def _make_segment_dict(self, segment_db, fields=None):
|
||||
res = {'id': segment_db['id'],
|
||||
'network_id': segment_db['network_id'],
|
||||
'name': segment_db['name'],
|
||||
'description': segment_db['description'],
|
||||
db.PHYSICAL_NETWORK: segment_db[db.PHYSICAL_NETWORK],
|
||||
db.NETWORK_TYPE: segment_db[db.NETWORK_TYPE],
|
||||
db.SEGMENTATION_ID: segment_db[db.SEGMENTATION_ID],
|
||||
|
@ -103,8 +105,16 @@ class SegmentDbMixin(common_db_mixin.CommonDbMixin):
|
|||
segmentation_id = segment[extension.SEGMENTATION_ID]
|
||||
if segmentation_id == constants.ATTR_NOT_SPECIFIED:
|
||||
segmentation_id = None
|
||||
name = segment['name']
|
||||
if name == constants.ATTR_NOT_SPECIFIED:
|
||||
name = None
|
||||
description = segment['description']
|
||||
if description == constants.ATTR_NOT_SPECIFIED:
|
||||
description = None
|
||||
args = {'id': segment_id,
|
||||
'network_id': network_id,
|
||||
'name': name,
|
||||
'description': description,
|
||||
db.PHYSICAL_NETWORK: physical_network,
|
||||
db.NETWORK_TYPE: network_type,
|
||||
db.SEGMENTATION_ID: segmentation_id}
|
||||
|
|
|
@ -80,7 +80,7 @@ class SegmentTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
|
|||
def _create_segment(self, fmt, expected_res_status=None, **kwargs):
|
||||
segment = {'segment': {}}
|
||||
for k, v in kwargs.items():
|
||||
segment['segment'][k] = str(v)
|
||||
segment['segment'][k] = None if v is None else str(v)
|
||||
|
||||
segment_req = self.new_create_request(
|
||||
'segments', segment, fmt)
|
||||
|
@ -141,6 +141,73 @@ class SegmentTestPlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||
return port_dict
|
||||
|
||||
|
||||
class TestSegmentNameDescription(SegmentTestCase):
|
||||
def setUp(self):
|
||||
super(TestSegmentNameDescription, self).setUp()
|
||||
with self.network() as network:
|
||||
self.network = network['network']
|
||||
|
||||
def _test_create_segment(self, expected=None, **kwargs):
|
||||
for d in (kwargs, expected):
|
||||
if d is None:
|
||||
continue
|
||||
d.setdefault('network_id', self.network['id'])
|
||||
d.setdefault('name', None)
|
||||
d.setdefault('description', None)
|
||||
d.setdefault('physical_network', 'phys_net')
|
||||
d.setdefault('network_type', 'net_type')
|
||||
d.setdefault('segmentation_id', 200)
|
||||
return super(TestSegmentNameDescription, self)._test_create_segment(
|
||||
expected, **kwargs)
|
||||
|
||||
def test_create_segment_no_name_description(self):
|
||||
self._test_create_segment(expected={})
|
||||
|
||||
def test_create_segment_with_name(self):
|
||||
expected_segment = {'name': 'segment_name'}
|
||||
self._test_create_segment(name='segment_name',
|
||||
expected=expected_segment)
|
||||
|
||||
def test_create_segment_with_description(self):
|
||||
expected_segment = {'description': 'A segment'}
|
||||
self._test_create_segment(description='A segment',
|
||||
expected=expected_segment)
|
||||
|
||||
def test_update_segment_set_name(self):
|
||||
segment = self._test_create_segment()
|
||||
result = self._update('segments',
|
||||
segment['segment']['id'],
|
||||
{'segment': {'name': 'Segment name'}},
|
||||
expected_code=webob.exc.HTTPOk.code)
|
||||
self.assertEqual('Segment name', result['segment']['name'])
|
||||
|
||||
def test_update_segment_set_description(self):
|
||||
segment = self._test_create_segment()
|
||||
result = self._update('segments',
|
||||
segment['segment']['id'],
|
||||
{'segment': {'description': 'Segment desc'}},
|
||||
expected_code=webob.exc.HTTPOk.code)
|
||||
self.assertEqual('Segment desc', result['segment']['description'])
|
||||
|
||||
def test_update_segment_set_name_to_none(self):
|
||||
segment = self._test_create_segment(
|
||||
description='A segment', name='segment')
|
||||
result = self._update('segments',
|
||||
segment['segment']['id'],
|
||||
{'segment': {'name': None}},
|
||||
expected_code=webob.exc.HTTPOk.code)
|
||||
self.assertEqual(None, result['segment']['name'])
|
||||
|
||||
def test_update_segment_set_description_to_none(self):
|
||||
segment = self._test_create_segment(
|
||||
description='A segment', name='segment')
|
||||
result = self._update('segments',
|
||||
segment['segment']['id'],
|
||||
{'segment': {'description': None}},
|
||||
expected_code=webob.exc.HTTPOk.code)
|
||||
self.assertEqual(None, result['segment']['description'])
|
||||
|
||||
|
||||
class TestSegment(SegmentTestCase):
|
||||
|
||||
def test_create_segment(self):
|
||||
|
|
|
@ -32,7 +32,7 @@ object_data = {
|
|||
'ExtraDhcpOpt': '1.0-632f689cbeb36328995a7aed1d0a78d3',
|
||||
'IPAllocationPool': '1.0-371016a6480ed0b4299319cb46d9215d',
|
||||
'NetworkPortSecurity': '1.0-b30802391a87945ee9c07582b4ff95e3',
|
||||
'NetworkSegment': '1.0-865567a6f70eb85cf33fb7a5575a4eab',
|
||||
'NetworkSegment': '1.0-40707ef6bd9a0bf095038158d995cc7d',
|
||||
'PortSecurity': '1.0-b30802391a87945ee9c07582b4ff95e3',
|
||||
'AllowedAddressPair': '1.0-9f9186b6f952fbf31d257b0458b852c0',
|
||||
'QosBandwidthLimitRule': '1.2-4e44a8f5c2895ab1278399f87b40a13d',
|
||||
|
|
|
@ -61,6 +61,10 @@ class Ml2DBTestCase(testlib_api.SqlTestCase):
|
|||
vif_type=vif_type,
|
||||
host=host))
|
||||
|
||||
@staticmethod
|
||||
def _sort_segments(segments):
|
||||
return sorted(segments, key=lambda d: d['segmentation_id'])
|
||||
|
||||
def _create_segments(self, segments, is_seg_dynamic=False,
|
||||
network_id='foo-network-id'):
|
||||
self._setup_neutron_network(network_id)
|
||||
|
@ -72,6 +76,7 @@ class Ml2DBTestCase(testlib_api.SqlTestCase):
|
|||
net_segments = segments_db.get_network_segments(
|
||||
self.ctx.session, network_id,
|
||||
filter_dynamic=is_seg_dynamic)
|
||||
net_segments = self._sort_segments(net_segments)
|
||||
|
||||
for segment_index, segment in enumerate(segments):
|
||||
self.assertEqual(segment, net_segments[segment_index])
|
||||
|
@ -116,8 +121,8 @@ class Ml2DBTestCase(testlib_api.SqlTestCase):
|
|||
net2segs = self._create_segments(segments2, network_id='net2')
|
||||
segs = segments_db.get_networks_segments(
|
||||
self.ctx.session, ['net1', 'net2'])
|
||||
self.assertEqual(net1segs, segs['net1'])
|
||||
self.assertEqual(net2segs, segs['net2'])
|
||||
self.assertEqual(net1segs, self._sort_segments(segs['net1']))
|
||||
self.assertEqual(net2segs, self._sort_segments(segs['net2']))
|
||||
|
||||
def test_get_networks_segments_no_segments(self):
|
||||
self._create_segments([], network_id='net1')
|
||||
|
|
|
@ -316,6 +316,7 @@ class TestAutoScheduleSegments(test_plugin.Ml2PluginV2TestCase,
|
|||
seg = self.segments_plugin.create_segment(
|
||||
self.ctx,
|
||||
{'segment': {'network_id': network_id,
|
||||
'name': None, 'description': None,
|
||||
'physical_network': 'physnet1',
|
||||
'network_type': 'vlan',
|
||||
'segmentation_id': constants.ATTR_NOT_SPECIFIED}})
|
||||
|
@ -529,6 +530,7 @@ class DHCPAgentWeightSchedulerTestCase(test_plugin.Ml2PluginV2TestCase):
|
|||
seg = self.segments_plugin.create_segment(
|
||||
self.ctx,
|
||||
{'segment': {'network_id': network_id,
|
||||
'name': None, 'description': None,
|
||||
'physical_network': 'physnet1',
|
||||
'network_type': 'vlan',
|
||||
'segmentation_id': constants.ATTR_NOT_SPECIFIED}})
|
||||
|
|
Loading…
Reference in New Issue