Merge "Add df_skydive_service to dragonflow"
This commit is contained in:
commit
a95344638c
|
@ -1,3 +1,4 @@
|
|||
#@IgnoreInspection BashAddShebang
|
||||
# dragonflow.sh - Devstack extras script to install Dragonflow
|
||||
|
||||
# Enable DPDK for Open vSwitch user space datapath
|
||||
|
@ -50,6 +51,10 @@ if [[ "$ENABLE_AGING_APP" == "True" ]]; then
|
|||
DEFAULT_APPS_LIST="aging,$DEFAULT_APPS_LIST"
|
||||
fi
|
||||
|
||||
if is_service_enabled df-skydive ; then
|
||||
SKYDIVE_ENDPOINT=${SKYDIVE_ENDPOINT:-$SERVICE_HOST:8082}
|
||||
fi
|
||||
|
||||
DF_APPS_LIST=${DF_APPS_LIST:-$DEFAULT_APPS_LIST}
|
||||
TUNNEL_TYPES=${TUNNEL_TYPE:-$DEFAULT_TUNNEL_TYPES}
|
||||
|
||||
|
@ -222,6 +227,19 @@ function init_neutron_sample_config {
|
|||
fi
|
||||
}
|
||||
|
||||
function configure_df_skydive {
|
||||
iniset $DRAGONFLOW_CONF df_skydive analyzer_endpoint "$SKYDIVE_ENDPOINT"
|
||||
if [[ -n "$DF_SKYDIVE_USER" ]]; then
|
||||
iniset $DRAGONFLOW_CONF df_skydive user "$DF_SKYDIVE_USER"
|
||||
fi
|
||||
local DF_SKYDIVE_PASSWORD=${DF_SKYDIVE_PASSWORD:-$ADMIN_PASSWORD}
|
||||
iniset $DRAGONFLOW_CONF df_skydive password "$DF_SKYDIVE_PASSWORD"
|
||||
if [[ -n "$DF_SKYDIVE_UPDATE_INTERVAL" ]]; then
|
||||
iniset $DRAGONFLOW_CONF df_skydive update_interval "$DF_SKYDIVE_UPDATE_INTERVAL"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function configure_df_plugin {
|
||||
echo "Configuring Neutron for Dragonflow"
|
||||
|
||||
|
@ -305,6 +323,10 @@ function configure_df_plugin {
|
|||
iniset $DRAGONFLOW_CONF df enable_selective_topology_distribution \
|
||||
"$DF_SELECTIVE_TOPO_DIST"
|
||||
configure_df_metadata_service
|
||||
|
||||
if is_service_enabled df-skydive ; then
|
||||
configure_df_skydive
|
||||
fi
|
||||
}
|
||||
|
||||
function install_zeromq {
|
||||
|
@ -492,6 +514,20 @@ function start_df_bgp_service {
|
|||
fi
|
||||
}
|
||||
|
||||
function start_df_skydive {
|
||||
if is_service_enabled df-skydive ; then
|
||||
echo "Starting Dragonflow skydive service"
|
||||
run_process df-skydive "$DF_SKYDIVE_SERVICE --config-file $NEUTRON_CONF --config-file $DRAGONFLOW_CONF"
|
||||
fi
|
||||
}
|
||||
|
||||
function stop_df_skydive {
|
||||
if is_service_enabled df-skydive ; then
|
||||
echo "Stopping Dragonflow skydive service"
|
||||
stop_process df-skydive
|
||||
fi
|
||||
}
|
||||
|
||||
function setup_rootwrap_filters {
|
||||
if [[ "$DF_INSTALL_DEBUG_ROOTWRAP_CONF" == "True" ]]; then
|
||||
echo "Adding rootwrap filters"
|
||||
|
@ -569,6 +605,7 @@ function handle_df_stack_post_install {
|
|||
start_df_bgp_service
|
||||
setup_rootwrap_filters
|
||||
create_tables_script
|
||||
start_df_skydive
|
||||
}
|
||||
|
||||
function handle_df_stack {
|
||||
|
@ -580,6 +617,7 @@ function handle_df_stack {
|
|||
}
|
||||
|
||||
function handle_df_unstack {
|
||||
stop_df_skydive
|
||||
stop_df_bgp_service
|
||||
stop_df_metadata_agent
|
||||
stop_df
|
||||
|
|
|
@ -28,6 +28,10 @@ DF_BGP_SERVICE=${DF_BGP_SERVICE:-"$NEUTRON_BIN_DIR/df-bgp-service"}
|
|||
# This can be overridden in the localrc file, set df-bgp to enable
|
||||
DR_MODE=${DR_MODE:-no-bgp}
|
||||
|
||||
# df-skydive
|
||||
DF_SKYDIVE_SERVICE=${DF_SKYDIVE_SERVICE:-"$NEUTRON_BIN_DIR/df-skydive-service"}
|
||||
|
||||
|
||||
DF_L2_RESPONDER=${DF_L2_RESPONDER:-'True'}
|
||||
|
||||
DF_MONITOR_TABLE_POLL_TIME=${DF_MONITOR_TABLE_POLL_TIME:-30}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
[[local|localrc]]
|
||||
|
||||
# These MUST come before the 'enable_plugin dragonflow' as the dragonflow
|
||||
# assumes the skydive analyzer is already installed
|
||||
enable_plugin skydive https://github.com/skydive-project/skydive.git
|
||||
enable_service skydive-agent skydive-analyzer
|
||||
|
||||
DATABASE_PASSWORD=password
|
||||
RABBIT_PASSWORD=password
|
||||
SERVICE_PASSWORD=password
|
||||
SERVICE_TOKEN=password
|
||||
ADMIN_PASSWORD=password
|
||||
|
||||
enable_plugin dragonflow https://git.openstack.org/openstack/dragonflow
|
||||
enable_service df-etcd
|
||||
enable_service etcd3
|
||||
enable_service df-controller
|
||||
enable_service df-etcd-pubsub-service
|
||||
|
||||
disable_service n-net
|
||||
enable_service q-svc
|
||||
enable_service df-l3-agent
|
||||
disable_service heat
|
||||
disable_service tempest
|
||||
|
||||
enable_service df-skydive
|
||||
|
||||
# Enable df-metadata (Dragonflow metadata service proxy) once nova is being used.
|
||||
enable_service df-metadata
|
||||
|
||||
# We have to disable the neutron L2 agent. DF does not use the L2 agent.
|
||||
disable_service q-agt
|
||||
|
||||
# We have to disable the neutron dhcp agent. DF does not use the dhcp agent.
|
||||
disable_service q-dhcp
|
|
@ -9,11 +9,10 @@
|
|||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import argparse
|
||||
import signal
|
||||
import sys
|
||||
import uuid
|
||||
|
||||
import cotyledon
|
||||
from jsonmodels import fields
|
||||
from oslo_log import log
|
||||
from skydive.rest.client import RESTClient
|
||||
|
@ -22,6 +21,7 @@ from skydive.websocket import client as skydive_client
|
|||
from dragonflow.common import utils as df_utils
|
||||
from dragonflow import conf as cfg
|
||||
from dragonflow.controller import df_config
|
||||
from dragonflow.controller import service as df_service
|
||||
from dragonflow.db import api_nb
|
||||
from dragonflow.db import model_framework as mf
|
||||
from dragonflow.db import model_proxy
|
||||
|
@ -32,66 +32,60 @@ LOG = log.getLogger(__name__)
|
|||
DRAGONFLOW_HOST_ID = 'dragonflow-skydive'
|
||||
DF_SKYDIVE_NAMESPACE_UUID = uuid.UUID('8a527b24-f0f5-4c1f-8f3d-6de400aa0145')
|
||||
|
||||
global_skydive_client = None
|
||||
|
||||
|
||||
class SkydiveClient(object):
|
||||
class SkydiveClient(cotyledon.Service):
|
||||
"""Main class that manages all the skydive operation."""
|
||||
def __init__(self, nb_api):
|
||||
protocol = WSClientDragonflowProtocol(nb_api)
|
||||
def __init__(self, worker_id, nb_api):
|
||||
super(SkydiveClient, self).__init__(worker_id)
|
||||
self.protocol = WSClientDragonflowProtocol(nb_api)
|
||||
self.websocket_client = skydive_client.WSClient(
|
||||
host_id=DRAGONFLOW_HOST_ID,
|
||||
endpoint='ws://{0}/ws/publisher'.format(
|
||||
cfg.CONF.df_skydive.analyzer_endpoint),
|
||||
protocol=lambda: protocol
|
||||
protocol=lambda: self.protocol,
|
||||
username=cfg.CONF.df_skydive.user,
|
||||
password=cfg.CONF.df_skydive.password
|
||||
)
|
||||
logged_in = self.websocket_client.login(
|
||||
cfg.CONF.df_skydive.analyzer_endpoint,
|
||||
cfg.CONF.df_skydive.user,
|
||||
cfg.CONF.df_skydive.password)
|
||||
if not logged_in:
|
||||
# TODO(snapiri) raise an exception
|
||||
LOG.error('Failed authenticating with SkyDive analyzer at %s',
|
||||
cfg.CONF.df_skydive.analyzer_endpoint)
|
||||
return
|
||||
self.websocket_client.connect()
|
||||
|
||||
@staticmethod
|
||||
def create():
|
||||
"""Create a new SkydiveClient
|
||||
:return a newly allocated SkydiveClient
|
||||
:rtype SkydiveClient
|
||||
"""
|
||||
df_utils.config_parse()
|
||||
nb_api = api_nb.NbApi.get_instance(False, True)
|
||||
return SkydiveClient(nb_api)
|
||||
try:
|
||||
self.websocket_client.connect()
|
||||
except RuntimeError:
|
||||
LOG.error('Failed connecting with SkyDive analyzer at %s',
|
||||
cfg.CONF.df_skydive.analyzer_endpoint)
|
||||
raise
|
||||
|
||||
def clear_dragonflow_items(self):
|
||||
"""Delete all the items created by DragonFlow"""
|
||||
restclient = RESTClient(cfg.CONF.df_skydive.analyzer_endpoint)
|
||||
edges = restclient.lookup_edges("G.E().Has('source': 'dragonflow')")
|
||||
for edge in edges:
|
||||
restclient = RESTClient(cfg.CONF.df_skydive.analyzer_endpoint,
|
||||
username=cfg.CONF.df_skydive.user,
|
||||
password=cfg.CONF.df_skydive.password)
|
||||
items = restclient.lookup_edges("G.E().Has('source', 'dragonflow')")
|
||||
for edge in items:
|
||||
edge_del_msg = skydive_client.WSMessage(
|
||||
"Graph",
|
||||
skydive_client.EdgeDeletedMsgType,
|
||||
edge
|
||||
)
|
||||
self.sendWSMessage(edge_del_msg)
|
||||
nodes = restclient.lookup_nodes("G.V().Has('source': 'dragonflow')")
|
||||
for node in nodes:
|
||||
self.protocol.sendWSMessage(edge_del_msg)
|
||||
items = restclient.lookup_nodes("G.V().Has('source', 'dragonflow')")
|
||||
for node in items:
|
||||
node_del_msg = skydive_client.WSMessage(
|
||||
"Graph",
|
||||
skydive_client.NodeDeletedMsgType,
|
||||
node
|
||||
)
|
||||
self.sendWSMessage(node_del_msg)
|
||||
self.protocol.sendWSMessage(node_del_msg)
|
||||
|
||||
def start(self):
|
||||
def run(self):
|
||||
"""Start communication with the SkyDive analyzer
|
||||
|
||||
This starts the operaiton of periodically querying the nb_api and
|
||||
sending all the objects to the SkyDive analyzer.
|
||||
"""
|
||||
super(SkydiveClient, self).run()
|
||||
# First clear all existing items
|
||||
self.clear_dragonflow_items()
|
||||
# Now start the loop
|
||||
self.websocket_client.start()
|
||||
|
||||
def schedule_stop(self, wait_time):
|
||||
|
@ -100,10 +94,11 @@ class SkydiveClient(object):
|
|||
:type wait_time: int
|
||||
"""
|
||||
loop = self.websocket_client.loop
|
||||
loop.call_later(wait_time, self.stop)
|
||||
loop.call_later(wait_time, self.terminate)
|
||||
|
||||
def stop(self):
|
||||
def terminate(self):
|
||||
"""Stop the process of sending the updates to the SkyDive analyzer"""
|
||||
super(SkydiveClient, self).terminate()
|
||||
self.websocket_client.stop()
|
||||
|
||||
|
||||
|
@ -280,31 +275,24 @@ class WSClientDragonflowProtocol(skydive_client.WSClientDebugProtocol):
|
|||
super(WSClientDragonflowProtocol, self).onClose(wasClean, code, reason)
|
||||
|
||||
|
||||
def signal_handler(signal, frame):
|
||||
if global_skydive_client:
|
||||
LOG.info('Stopping SkyDive service')
|
||||
global_skydive_client.stop()
|
||||
|
||||
|
||||
def set_signal_handler():
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
signal.signal(signal.SIGHUP, signal_handler)
|
||||
def start(is_service):
|
||||
"""main method"""
|
||||
df_config.init(sys.argv)
|
||||
df_utils.config_parse()
|
||||
nb_api = api_nb.NbApi.get_instance(False, True)
|
||||
if is_service:
|
||||
df_service.register_service('df-skydive-service', nb_api)
|
||||
service_manager = cotyledon.ServiceManager()
|
||||
service_manager.add(SkydiveClient, workers=1, args=(nb_api,))
|
||||
service_manager.run()
|
||||
|
||||
|
||||
def main():
|
||||
"""main method"""
|
||||
df_config.init(sys.argv)
|
||||
parser = argparse.ArgumentParser(description='SkyDive integration service')
|
||||
parser.add_argument('-t', '--runtime', type=int,
|
||||
help='Total runtime (default 0 = infinite)')
|
||||
args = parser.parse_args()
|
||||
global global_skydive_client
|
||||
global_skydive_client = SkydiveClient.create()
|
||||
if args.runtime:
|
||||
global_skydive_client.schedule_stop(args.runtime)
|
||||
global_skydive_client.clear_dragonflow_items()
|
||||
set_signal_handler()
|
||||
global_skydive_client.start()
|
||||
start(False)
|
||||
|
||||
|
||||
def service_main():
|
||||
start(True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -26,9 +26,11 @@ six>=1.10.0 # MIT
|
|||
httplib2>=0.9.1 # MIT
|
||||
WebOb>=1.7.1 # MIT
|
||||
jsonmodels>=2.1.3 # BSD License (3 clause)
|
||||
skydive-client>=0.4.1 # Apache-2.0
|
||||
skydive-client>=0.4.4 # Apache-2.0
|
||||
cotyledon>=1.3.0 # Apache-2.0
|
||||
|
||||
# These repos are installed from git in OpenStack CI if the job
|
||||
# configures them as required-projects:
|
||||
neutron>=12.0.0 # Apache-2.0
|
||||
networking-sfc>=6.0.0 # Apache-2.0
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ console_scripts =
|
|||
df-l3-agent = dragonflow.cmd.eventlet.df_l3_agent:main
|
||||
df-metadata-service = dragonflow.cmd.eventlet.df_metadata_service:main
|
||||
df-bgp-service = dragonflow.cmd.eventlet.df_bgp_service:main
|
||||
df-skydive-service= dragonflow.cmd.df_skydive_service:service_main
|
||||
dragonflow.pubsub_driver =
|
||||
zmq_pubsub_driver = dragonflow.db.pubsub_drivers.zmq_pubsub_driver:ZMQPubSub
|
||||
zmq_pubsub_multiproc_driver = dragonflow.db.pubsub_drivers.zmq_pubsub_driver:ZMQPubSubMultiproc
|
||||
|
|
Loading…
Reference in New Issue