From d3ff8f323b2827dc14ee550a99a5661fee2294cb Mon Sep 17 00:00:00 2001 From: Carlos Goncalves Date: Mon, 26 Jun 2017 11:16:00 +0200 Subject: Backport Neutron port data plane status JIRA: APEX-444 JIRA: DOCTOR-102 Change-Id: Idc40aa549fb1aae077a9e6b84225833a9c7c5b72 Signed-off-by: Carlos Goncalves --- build/patches/neutron_server_dps.patch | 393 +++++++++++++++++++++++++++++++++ 1 file changed, 393 insertions(+) create mode 100644 build/patches/neutron_server_dps.patch (limited to 'build/patches/neutron_server_dps.patch') diff --git a/build/patches/neutron_server_dps.patch b/build/patches/neutron_server_dps.patch new file mode 100644 index 00000000..6136aecc --- /dev/null +++ b/build/patches/neutron_server_dps.patch @@ -0,0 +1,393 @@ +From 89de63de05e296af583032cb17a3d76b4b4d6a40 Mon Sep 17 00:00:00 2001 +From: Carlos Goncalves +Date: Mon, 23 Jan 2017 19:53:04 +0000 +Subject: [PATCH] Port data plane status extension implementation + +Implements the port data plane status extension. Third parties +can report via Neutron API issues in the underlying data plane +affecting connectivity from/to Neutron ports. + +Supported statuses: + - None: no status being reported; default value + - ACTIVE: all is up and running + - DOWN: no traffic can flow from/to the Neutron port + +Setting attribute available to admin or any user with specific role +(default role: data_plane_integrator). + +ML2 extension driver loaded on request via configuration: + + [ml2] + extension_drivers = data_plane_status + +Related-Bug: #1598081 +Related-Bug: #1575146 + +DocImpact: users can get status of the underlying port data plane; +attribute writable by admin users and users granted the +'data-plane-integrator' role. +APIImpact: port now has data_plane_status attr, set on port update + +Implements: blueprint port-data-plane-status + +Depends-On: I04eef902b3310f799b1ce7ea44ed7cf77c74da04 +Change-Id: Ic9e1e3ed9e3d4b88a4292114f4cb4192ac4b3502 +--- + neutron/db/data_plane_status_db.py | 48 ++++++++++++++++++++++ + .../alembic_migrations/versions/EXPAND_HEAD | 2 +- + .../804a3c76314c_add_data_plane_status_to_port.py | 39 ++++++++++++++++++ + neutron/db/models/data_plane_status.py | 34 +++++++++++++++ + neutron/extensions/data_plane_status.py | 47 +++++++++++++++++++++ + .../objects/port/extensions/data_plane_status.py | 37 +++++++++++++++++ + neutron/objects/ports.py | 14 ++++++- + .../plugins/ml2/extensions/data_plane_status.py | 41 ++++++++++++++++++ + 8 files changed, 260 insertions(+), 2 deletions(-) + create mode 100644 neutron/db/data_plane_status_db.py + create mode 100644 neutron/db/migration/alembic_migrations/versions/pike/expand/804a3c76314c_add_data_plane_status_to_port.py + create mode 100644 neutron/db/models/data_plane_status.py + create mode 100644 neutron/extensions/data_plane_status.py + create mode 100644 neutron/objects/port/extensions/data_plane_status.py + create mode 100644 neutron/plugins/ml2/extensions/data_plane_status.py + +diff --git a/neutron/db/data_plane_status_db.py b/neutron/db/data_plane_status_db.py +new file mode 100644 +index 000000000..4e5c23aef +--- /dev/null ++++ b/neutron/db/data_plane_status_db.py +@@ -0,0 +1,48 @@ ++# Copyright (c) 2017 NEC Corporation. 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 data_plane_status as dps_lib ++ ++from neutron.objects.port.extensions import data_plane_status as dps_obj ++ ++ ++class DataPlaneStatusMixin(object): ++ """Mixin class to add data plane status to a port""" ++ ++ def _process_create_port_data_plane_status(self, context, data, res): ++ obj = dps_obj.PortDataPlaneStatus(context, port_id=res['id'], ++ data_plane_status=data[dps_lib.DATA_PLANE_STATUS]) ++ obj.create() ++ res[dps_lib.DATA_PLANE_STATUS] = data[dps_lib.DATA_PLANE_STATUS] ++ ++ def _process_update_port_data_plane_status(self, context, data, ++ res): ++ if dps_lib.DATA_PLANE_STATUS not in data: ++ return ++ ++ obj = dps_obj.PortDataPlaneStatus.get_object(context, ++ port_id=res['id']) ++ if obj: ++ obj.data_plane_status = data[dps_lib.DATA_PLANE_STATUS] ++ obj.update() ++ res[dps_lib.DATA_PLANE_STATUS] = data[dps_lib.DATA_PLANE_STATUS] ++ else: ++ self._process_create_port_data_plane_status(context, data, res) ++ ++ def _extend_port_data_plane_status(self, port_res, port_db): ++ port_res[dps_lib.DATA_PLANE_STATUS] = None ++ ++ if port_db.get(dps_lib.DATA_PLANE_STATUS): ++ port_res[dps_lib.DATA_PLANE_STATUS] = ( ++ port_db[dps_lib.DATA_PLANE_STATUS].data_plane_status) +diff --git a/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD b/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD +index 1c625bc83..8c1796ba3 100644 +--- a/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD ++++ b/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD +@@ -1 +1 @@ +-a9c43481023c ++804a3c76314c +diff --git a/neutron/db/migration/alembic_migrations/versions/pike/expand/804a3c76314c_add_data_plane_status_to_port.py b/neutron/db/migration/alembic_migrations/versions/pike/expand/804a3c76314c_add_data_plane_status_to_port.py +new file mode 100644 +index 000000000..bd4d1472b +--- /dev/null ++++ b/neutron/db/migration/alembic_migrations/versions/pike/expand/804a3c76314c_add_data_plane_status_to_port.py +@@ -0,0 +1,39 @@ ++# Copyright 2017 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. ++# ++ ++"""Add data_plane_status to Port ++ ++Revision ID: 804a3c76314c ++Revises: a9c43481023c ++Create Date: 2017-01-17 13:51:45.737987 ++ ++""" ++ ++# revision identifiers, used by Alembic. ++revision = '804a3c76314c' ++down_revision = 'a9c43481023c' ++ ++from alembic import op ++import sqlalchemy as sa ++ ++ ++def upgrade(): ++ op.create_table('portdataplanestatuses', ++ sa.Column('port_id', sa.String(36), ++ sa.ForeignKey('ports.id', ++ ondelete="CASCADE"), ++ primary_key=True, index=True), ++ sa.Column('data_plane_status', sa.String(length=16), ++ nullable=True)) +diff --git a/neutron/db/models/data_plane_status.py b/neutron/db/models/data_plane_status.py +new file mode 100644 +index 000000000..ada10af55 +--- /dev/null ++++ b/neutron/db/models/data_plane_status.py +@@ -0,0 +1,34 @@ ++# Copyright (c) 2017 NEC Corporation. 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.db import model_base ++import sqlalchemy as sa ++from sqlalchemy import orm ++ ++from neutron.db import models_v2 ++ ++ ++class PortDataPlaneStatus(model_base.BASEV2): ++ __tablename__ = 'portdataplanestatuses' ++ ++ port_id = sa.Column(sa.String(36), ++ sa.ForeignKey('ports.id', ondelete="CASCADE"), ++ primary_key=True, index=True) ++ data_plane_status = sa.Column(sa.String(16), nullable=True) ++ port = orm.relationship( ++ models_v2.Port, load_on_pending=True, ++ backref=orm.backref("data_plane_status", ++ lazy='joined', uselist=False, ++ cascade='delete')) ++ revises_on_change = ('port', ) +diff --git a/neutron/extensions/data_plane_status.py b/neutron/extensions/data_plane_status.py +new file mode 100644 +index 000000000..8e225e670 +--- /dev/null ++++ b/neutron/extensions/data_plane_status.py +@@ -0,0 +1,47 @@ ++# Copyright (c) 2017 NEC Corporation. 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 data_plane_status ++from neutron_lib.api import extensions ++ ++ ++class Data_plane_status(extensions.ExtensionDescriptor): ++ ++ @classmethod ++ def get_name(cls): ++ return data_plane_status.NAME ++ ++ @classmethod ++ def get_alias(cls): ++ return data_plane_status.ALIAS ++ ++ @classmethod ++ def get_description(cls): ++ return data_plane_status.DESCRIPTION ++ ++ @classmethod ++ def get_updated(cls): ++ return data_plane_status.UPDATED_TIMESTAMP ++ ++ def get_required_extensions(self): ++ return data_plane_status.REQUIRED_EXTENSIONS or [] ++ ++ def get_optional_extensions(self): ++ return data_plane_status.OPTIONAL_EXTENSIONS or [] ++ ++ def get_extended_resources(self, version): ++ if version == "2.0": ++ return data_plane_status.RESOURCE_ATTRIBUTE_MAP ++ else: ++ return {} +diff --git a/neutron/objects/port/extensions/data_plane_status.py b/neutron/objects/port/extensions/data_plane_status.py +new file mode 100644 +index 000000000..bd5858123 +--- /dev/null ++++ b/neutron/objects/port/extensions/data_plane_status.py +@@ -0,0 +1,37 @@ ++# Copyright (c) 2017 NEC Corporation. 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 oslo_versionedobjects import base as obj_base ++from oslo_versionedobjects import fields as obj_fields ++ ++from neutron.db.models import data_plane_status as db_models ++from neutron.objects import base ++from neutron.objects import common_types ++ ++ ++@obj_base.VersionedObjectRegistry.register ++class PortDataPlaneStatus(base.NeutronDbObject): ++ # Version 1.0: Initial version ++ VERSION = "1.0" ++ ++ db_model = db_models.PortDataPlaneStatus ++ ++ primary_keys = ['port_id'] ++ ++ fields = { ++ 'port_id': common_types.UUIDField(), ++ 'data_plane_status': obj_fields.StringField(), ++ } ++ ++ foreign_keys = {'Port': {'port_id': 'id'}} +diff --git a/neutron/objects/ports.py b/neutron/objects/ports.py +index bbddb4dde..dd83db147 100644 +--- a/neutron/objects/ports.py ++++ b/neutron/objects/ports.py +@@ -13,6 +13,7 @@ + # under the License. + + import netaddr ++from oslo_utils import versionutils + from oslo_versionedobjects import base as obj_base + from oslo_versionedobjects import fields as obj_fields + +@@ -206,7 +207,8 @@ class PortDNS(base.NeutronDbObject): + @obj_base.VersionedObjectRegistry.register + class Port(base.NeutronDbObject): + # Version 1.0: Initial version +- VERSION = '1.0' ++ # Version 1.1: Add data_plane_status field ++ VERSION = '1.1' + + db_model = models_v2.Port + +@@ -227,6 +229,9 @@ class Port(base.NeutronDbObject): + 'binding': obj_fields.ObjectField( + 'PortBinding', nullable=True + ), ++ 'data_plane_status': obj_fields.ObjectField( ++ 'PortDataPlaneStatus', nullable=True ++ ), + 'dhcp_options': obj_fields.ListOfObjectsField( + 'ExtraDhcpOpt', nullable=True + ), +@@ -260,6 +265,7 @@ class Port(base.NeutronDbObject): + 'allowed_address_pairs', + 'binding', + 'binding_levels', ++ 'data_plane_status', + 'dhcp_options', + 'distributed_binding', + 'dns', +@@ -374,3 +380,9 @@ class Port(base.NeutronDbObject): + else: + self.qos_policy_id = None + self.obj_reset_changes(['qos_policy_id']) ++ ++ def obj_make_compatible(self, primitive, target_version): ++ _target_version = versionutils.convert_version_to_tuple(target_version) ++ ++ if _target_version < (1, 1): ++ primitive.pop('data_plane_status') +diff --git a/neutron/plugins/ml2/extensions/data_plane_status.py b/neutron/plugins/ml2/extensions/data_plane_status.py +new file mode 100644 +index 000000000..850dafab6 +--- /dev/null ++++ b/neutron/plugins/ml2/extensions/data_plane_status.py +@@ -0,0 +1,41 @@ ++# Copyright (c) 2017 NEC Corporation. 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 data_plane_status as dps_lib ++from oslo_log import log as logging ++ ++from neutron.db import data_plane_status_db as dps_db ++from neutron.plugins.ml2 import driver_api as api ++ ++LOG = logging.getLogger(__name__) ++ ++ ++class DataPlaneStatusExtensionDriver(api.ExtensionDriver, ++ dps_db.DataPlaneStatusMixin): ++ _supported_extension_alias = 'data-plane-status' ++ ++ def initialize(self): ++ LOG.info("DataPlaneStatusExtensionDriver initialization complete") ++ ++ @property ++ def extension_alias(self): ++ return self._supported_extension_alias ++ ++ def process_update_port(self, plugin_context, data, result): ++ if dps_lib.DATA_PLANE_STATUS in data: ++ self._process_update_port_data_plane_status(plugin_context, ++ data, result) ++ ++ def extend_port_dict(self, session, db_data, result): ++ self._extend_port_data_plane_status(result, db_data) +-- +2.12.3 + -- cgit 1.2.3-korg