32e0e2178d
when updating a port 'binding:host_id' is reset if not specified among the parameter to be updated. As a result, a None value for 'binding:host_id' is sent from the notifier which might potentially cause consumers to not work properly. Closes-Bug: #1245310 Change-Id: Icfb5179940cca9f8a705eb36bdbfcbc8a421a272
114 lines
4.3 KiB
Python
114 lines
4.3 KiB
Python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
|
|
# Copyright 2013 IBM Corp.
|
|
# 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.
|
|
# @author: Yong Sheng Gong, IBM, Corp.
|
|
|
|
import sqlalchemy as sa
|
|
from sqlalchemy import orm
|
|
|
|
from neutron.api.v2 import attributes
|
|
from neutron.db import db_base_plugin_v2
|
|
from neutron.db import model_base
|
|
from neutron.db import models_v2
|
|
from neutron.db import portbindings_base
|
|
from neutron.extensions import portbindings
|
|
|
|
|
|
class PortBindingPort(model_base.BASEV2):
|
|
port_id = sa.Column(sa.String(36),
|
|
sa.ForeignKey('ports.id', ondelete="CASCADE"),
|
|
primary_key=True)
|
|
host = sa.Column(sa.String(255), nullable=False)
|
|
port = orm.relationship(
|
|
models_v2.Port,
|
|
backref=orm.backref("portbinding",
|
|
lazy='joined', uselist=False,
|
|
cascade='delete'))
|
|
|
|
|
|
class PortBindingMixin(portbindings_base.PortBindingBaseMixin):
|
|
extra_binding_dict = None
|
|
|
|
def _port_model_hook(self, context, original_model, query):
|
|
query = query.outerjoin(PortBindingPort,
|
|
(original_model.id ==
|
|
PortBindingPort.port_id))
|
|
return query
|
|
|
|
def _port_result_filter_hook(self, query, filters):
|
|
values = filters and filters.get(portbindings.HOST_ID, [])
|
|
if not values:
|
|
return query
|
|
if len(values) == 1:
|
|
query = query.filter(PortBindingPort.host == values[0])
|
|
else:
|
|
query = query.filter(PortBindingPort.host.in_(values))
|
|
return query
|
|
|
|
db_base_plugin_v2.NeutronDbPluginV2.register_model_query_hook(
|
|
models_v2.Port,
|
|
"portbindings_port",
|
|
'_port_model_hook',
|
|
None,
|
|
'_port_result_filter_hook')
|
|
|
|
def _process_portbindings_create_and_update(self, context, port_data,
|
|
port):
|
|
binding_profile = port.get(portbindings.PROFILE)
|
|
binding_profile_set = attributes.is_attr_set(binding_profile)
|
|
if not binding_profile_set and binding_profile is not None:
|
|
del port[portbindings.PROFILE]
|
|
host = port_data.get(portbindings.HOST_ID)
|
|
host_set = attributes.is_attr_set(host)
|
|
with context.session.begin(subtransactions=True):
|
|
bind_port = context.session.query(
|
|
PortBindingPort).filter_by(port_id=port['id']).first()
|
|
if host_set:
|
|
if not bind_port:
|
|
context.session.add(PortBindingPort(port_id=port['id'],
|
|
host=host))
|
|
else:
|
|
bind_port.host = host
|
|
else:
|
|
host = (bind_port and bind_port.host or None)
|
|
self._extend_port_dict_binding_host(port, host)
|
|
|
|
def get_port_host(self, context, port_id):
|
|
with context.session.begin(subtransactions=True):
|
|
bind_port = context.session.query(
|
|
PortBindingPort).filter_by(port_id=port_id).first()
|
|
return bind_port and bind_port.host or None
|
|
|
|
def _extend_port_dict_binding_host(self, port_res, host):
|
|
super(PortBindingMixin, self).extend_port_dict_binding(
|
|
port_res, None)
|
|
port_res[portbindings.HOST_ID] = host
|
|
|
|
def extend_port_dict_binding(self, port_res, port_db):
|
|
host = (port_db.portbinding and port_db.portbinding.host or None)
|
|
self._extend_port_dict_binding_host(port_res, host)
|
|
|
|
|
|
def _extend_port_dict_binding(plugin, port_res, port_db):
|
|
if not isinstance(plugin, PortBindingMixin):
|
|
return
|
|
plugin.extend_port_dict_binding(port_res, port_db)
|
|
|
|
|
|
# Register dict extend functions for ports
|
|
db_base_plugin_v2.NeutronDbPluginV2.register_dict_extend_funcs(
|
|
attributes.PORTS, [_extend_port_dict_binding])
|