Use ovs db notification to update metadata flows

This patch will use the notification from ovs db to update/delete
the OpenFlows for metadata service. So that when metadata proxy
restarts, the latest information can be upadted in OpenFlow. And thus,
the vm can still use metadata even if the metadata proxy restarts.

Change-Id: Idaf3060d80a95b210ca4934bd9b3ab29a7c6fe5a
Closes-bug: #1613615
This commit is contained in:
Hong Hui Xiao 2016-08-27 12:02:56 +08:00 committed by Li Ma
parent 00b49a8a11
commit 19232467d6
8 changed files with 62 additions and 23 deletions

View File

@ -137,7 +137,7 @@ function configure_df_metadata_service {
iniset $NEUTRON_CONF DEFAULT metadata_proxy_shared_secret $METADATA_PROXY_SHARED_SECRET
iniset $NEUTRON_CONF df_metadata ip "$DF_METADATA_SERVICE_IP"
iniset $NEUTRON_CONF df_metadata port "$DF_METADATA_SERVICE_PORT"
iniset $NEUTRON_CONF df_metadata interface "$DF_METADATA_SERVICE_INTERFACE"
iniset $NEUTRON_CONF df metadata_interface "$DF_METADATA_SERVICE_INTERFACE"
fi
}

View File

@ -11,24 +11,33 @@
# under the License.
from oslo_config import cfg
from oslo_log import log
from neutron.agent.common import utils
from neutron.agent.linux import ip_lib
from neutron.agent.metadata import config as metadata_conf
from neutron.common import config
from neutron import wsgi
from dragonflow._i18n import _LI
from dragonflow.common import common_params
from dragonflow.controller import metadata_service_app
import sys
LOG = log.getLogger(__name__)
METADATA_ROUTE_TABLE_ID = '2'
def environment_setup():
bridge = cfg.CONF.df.integration_bridge
interface = cfg.CONF.df_metadata.interface
interface = cfg.CONF.df.metadata_interface
if ip_lib.device_exists(interface):
LOG.info(_LI("Device %s already exists"), interface)
return
cmd = ["ovs-vsctl", "add-port", bridge, interface,
"--", "set", "Interface", interface, "type=internal"]
utils.execute(cmd, run_as_root=True)
@ -50,7 +59,7 @@ def environment_setup():
def environment_destroy():
bridge = cfg.CONF.df.integration_bridge
interface = cfg.CONF.df_metadata.interface
interface = cfg.CONF.df.metadata_interface
cmd = ["ovs-vsctl", "del-port", bridge, interface]
utils.execute(cmd, run_as_root=True, check_exit_code=[0])

View File

@ -132,5 +132,10 @@ df_opts = [
cfg.StrOpt("vhost_sock_dir",
default="/var/run/openvswitch",
help=_("The directory in which vhost virtio socket"
"is created by all the vswitch daemons"))
"is created by all the vswitch daemons")),
cfg.StrOpt(
'metadata_interface',
default='tap-metadata',
help=_('The name of the interface to bind the metadata service proxy'),
)
]

View File

@ -544,10 +544,12 @@ class DfLocalController(object):
self._associate_floatingip(new_floatingip)
def ovs_port_updated(self, ovs_port):
self.open_flow_app.notify_ovs_port_updated(ovs_port)
self.topology.ovs_port_updated(ovs_port)
def ovs_port_deleted(self, ovs_port_id):
self.topology.ovs_port_deleted(ovs_port_id)
def ovs_port_deleted(self, ovs_port):
self.open_flow_app.notify_ovs_port_deleted(ovs_port)
self.topology.ovs_port_deleted(ovs_port.get_id())
def ovs_sync_finished(self):
self.open_flow_app.notify_ovs_sync_finished()

View File

@ -23,7 +23,6 @@ import webob
from oslo_config import cfg
from oslo_log import log
from oslo_service import loopingcall
from oslo_utils import encodeutils
from neutron.agent.ovsdb.native import idlutils
@ -64,11 +63,6 @@ options = [
default='18080',
help=_('The port to which the DF metadata service proxy is bound'),
),
cfg.StrOpt(
'interface',
default='tap-metadata',
help=_('The name of the interface to bind the metadata service proxy'),
),
]
@ -85,17 +79,39 @@ class MetadataServiceApp(df_base_app.DFlowApp):
cfg.CONF.register_opts(options, group='df_metadata')
self._ip = cfg.CONF.df_metadata.ip
self._port = cfg.CONF.df_metadata.port
self._interface = cfg.CONF.df_metadata.interface
self._interface = cfg.CONF.df.metadata_interface
def ovs_sync_started(self):
self.initialize()
def ovs_port_updated(self, ovs_port):
if ovs_port.get_name() != cfg.CONF.df.metadata_interface:
return
def initialize(self):
loopingcall.FixedIntervalLoopingCall(
self._wait_for_tap_metadata_interface
).start(0, 1)
self._add_metadata_interface_flows()
def _wait_for_tap_metadata_interface(self):
def ovs_port_deleted(self, ovs_port):
if ovs_port.get_name() != cfg.CONF.df.metadata_interface:
return
self._remove_metadata_interface_flows()
def _remove_metadata_interface_flows(self):
if not self._ofport:
return
parser = self.get_datapath().ofproto_parser
ofproto = self.get_datapath().ofproto
self.mod_flow(
datapath=self.get_datapath(),
table_id=const.INGRESS_CLASSIFICATION_DISPATCH_TABLE,
command=ofproto.OFPFC_DELETE,
priority=const.PRIORITY_MEDIUM,
out_port=ofproto.OFPP_ANY,
out_group=ofproto.OFPG_ANY,
match=parser.OFPMatch(in_port=self._ofport))
self._ofport = None
def _add_metadata_interface_flows(self):
idl = self.vswitch_api.idl
if not idl:
return
@ -116,7 +132,6 @@ class MetadataServiceApp(df_base_app.DFlowApp):
if ofport <= 0:
return
self._add_tap_metadata_port(ofport, interface.mac_in_use[0])
raise loopingcall.LoopingCallDone()
def _add_tap_metadata_port(self, ofport, mac):
"""

View File

@ -133,6 +133,12 @@ class RyuDFAdapter(OFPHandler):
def notify_ovs_sync_started(self):
self.dispatcher.dispatch('ovs_sync_started')
def notify_ovs_port_updated(self, ovs_port):
self.dispatcher.dispatch('ovs_port_updated', ovs_port)
def notify_ovs_port_deleted(self, ovs_port):
self.dispatcher.dispatch('ovs_port_deleted', ovs_port)
def notify_associate_floatingip(self, floatingip):
self.dispatcher.dispatch('associate_floatingip', floatingip)

View File

@ -259,8 +259,8 @@ class NbApi(object):
elif action == 'sync_started':
self.controller.ovs_sync_started()
elif action == 'delete':
ovs_port_id = key
self.controller.ovs_port_deleted(ovs_port_id)
ovs_port = OvsPort(value)
self.controller.ovs_port_deleted(ovs_port)
elif 'log' == action:
message = _LI(
'Log event (Info): '

View File

@ -419,6 +419,8 @@ class OvsdbMonitor(object):
constants.OVS_BRIDGE_INTERFACE)
def _is_handle_interface_update(self, interface):
if interface.name == cfg.CONF.df.metadata_interface:
return True
if interface.type not in self.interface_type:
return False
if interface.name.startswith('qg'):