Add df_skydive_service to dragonflow
To enable skydive, one should now enable the service in the local.conf file using the following line: enable_service df_skydive If you would like to install the SkyDive analyzer on the same node, the SkyDive install lines MUST be before the DragonFlow ones! Please see doc/source/single-node-conf/etcd_skydive_local_controller.conf file for usage example Change-Id: I66c3eaf18904ae1c109d0ca8007269c41261d791 Depends-On: c5921051d7bc05d2c29494be842329e2ffcc008a Related-Bug: #1749429
This commit is contained in:
parent
439e528add
commit
7be2d258e2
|
@ -1,3 +1,4 @@
|
||||||
|
#@IgnoreInspection BashAddShebang
|
||||||
# dragonflow.sh - Devstack extras script to install Dragonflow
|
# dragonflow.sh - Devstack extras script to install Dragonflow
|
||||||
|
|
||||||
# Enable DPDK for Open vSwitch user space datapath
|
# 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"
|
DEFAULT_APPS_LIST="aging,$DEFAULT_APPS_LIST"
|
||||||
fi
|
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}
|
DF_APPS_LIST=${DF_APPS_LIST:-$DEFAULT_APPS_LIST}
|
||||||
TUNNEL_TYPES=${TUNNEL_TYPE:-$DEFAULT_TUNNEL_TYPES}
|
TUNNEL_TYPES=${TUNNEL_TYPE:-$DEFAULT_TUNNEL_TYPES}
|
||||||
|
|
||||||
|
@ -222,6 +227,19 @@ function init_neutron_sample_config {
|
||||||
fi
|
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 {
|
function configure_df_plugin {
|
||||||
echo "Configuring Neutron for Dragonflow"
|
echo "Configuring Neutron for Dragonflow"
|
||||||
|
|
||||||
|
@ -305,6 +323,10 @@ function configure_df_plugin {
|
||||||
iniset $DRAGONFLOW_CONF df enable_selective_topology_distribution \
|
iniset $DRAGONFLOW_CONF df enable_selective_topology_distribution \
|
||||||
"$DF_SELECTIVE_TOPO_DIST"
|
"$DF_SELECTIVE_TOPO_DIST"
|
||||||
configure_df_metadata_service
|
configure_df_metadata_service
|
||||||
|
|
||||||
|
if is_service_enabled df-skydive ; then
|
||||||
|
configure_df_skydive
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function install_zeromq {
|
function install_zeromq {
|
||||||
|
@ -492,6 +514,20 @@ function start_df_bgp_service {
|
||||||
fi
|
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 {
|
function setup_rootwrap_filters {
|
||||||
if [[ "$DF_INSTALL_DEBUG_ROOTWRAP_CONF" == "True" ]]; then
|
if [[ "$DF_INSTALL_DEBUG_ROOTWRAP_CONF" == "True" ]]; then
|
||||||
echo "Adding rootwrap filters"
|
echo "Adding rootwrap filters"
|
||||||
|
@ -569,6 +605,7 @@ function handle_df_stack_post_install {
|
||||||
start_df_bgp_service
|
start_df_bgp_service
|
||||||
setup_rootwrap_filters
|
setup_rootwrap_filters
|
||||||
create_tables_script
|
create_tables_script
|
||||||
|
start_df_skydive
|
||||||
}
|
}
|
||||||
|
|
||||||
function handle_df_stack {
|
function handle_df_stack {
|
||||||
|
@ -580,6 +617,7 @@ function handle_df_stack {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handle_df_unstack {
|
function handle_df_unstack {
|
||||||
|
stop_df_skydive
|
||||||
stop_df_bgp_service
|
stop_df_bgp_service
|
||||||
stop_df_metadata_agent
|
stop_df_metadata_agent
|
||||||
stop_df
|
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
|
# This can be overridden in the localrc file, set df-bgp to enable
|
||||||
DR_MODE=${DR_MODE:-no-bgp}
|
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_L2_RESPONDER=${DF_L2_RESPONDER:-'True'}
|
||||||
|
|
||||||
DF_MONITOR_TABLE_POLL_TIME=${DF_MONITOR_TABLE_POLL_TIME:-30}
|
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
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
import argparse
|
|
||||||
import signal
|
|
||||||
import sys
|
import sys
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
import cotyledon
|
||||||
from jsonmodels import fields
|
from jsonmodels import fields
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
from skydive.rest.client import RESTClient
|
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.common import utils as df_utils
|
||||||
from dragonflow import conf as cfg
|
from dragonflow import conf as cfg
|
||||||
from dragonflow.controller import df_config
|
from dragonflow.controller import df_config
|
||||||
|
from dragonflow.controller import service as df_service
|
||||||
from dragonflow.db import api_nb
|
from dragonflow.db import api_nb
|
||||||
from dragonflow.db import model_framework as mf
|
from dragonflow.db import model_framework as mf
|
||||||
from dragonflow.db import model_proxy
|
from dragonflow.db import model_proxy
|
||||||
|
@ -32,66 +32,60 @@ LOG = log.getLogger(__name__)
|
||||||
DRAGONFLOW_HOST_ID = 'dragonflow-skydive'
|
DRAGONFLOW_HOST_ID = 'dragonflow-skydive'
|
||||||
DF_SKYDIVE_NAMESPACE_UUID = uuid.UUID('8a527b24-f0f5-4c1f-8f3d-6de400aa0145')
|
DF_SKYDIVE_NAMESPACE_UUID = uuid.UUID('8a527b24-f0f5-4c1f-8f3d-6de400aa0145')
|
||||||
|
|
||||||
global_skydive_client = None
|
|
||||||
|
|
||||||
|
class SkydiveClient(cotyledon.Service):
|
||||||
class SkydiveClient(object):
|
|
||||||
"""Main class that manages all the skydive operation."""
|
"""Main class that manages all the skydive operation."""
|
||||||
def __init__(self, nb_api):
|
def __init__(self, worker_id, nb_api):
|
||||||
protocol = WSClientDragonflowProtocol(nb_api)
|
super(SkydiveClient, self).__init__(worker_id)
|
||||||
|
self.protocol = WSClientDragonflowProtocol(nb_api)
|
||||||
self.websocket_client = skydive_client.WSClient(
|
self.websocket_client = skydive_client.WSClient(
|
||||||
host_id=DRAGONFLOW_HOST_ID,
|
host_id=DRAGONFLOW_HOST_ID,
|
||||||
endpoint='ws://{0}/ws/publisher'.format(
|
endpoint='ws://{0}/ws/publisher'.format(
|
||||||
cfg.CONF.df_skydive.analyzer_endpoint),
|
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
|
try:
|
||||||
def create():
|
self.websocket_client.connect()
|
||||||
"""Create a new SkydiveClient
|
except RuntimeError:
|
||||||
:return a newly allocated SkydiveClient
|
LOG.error('Failed connecting with SkyDive analyzer at %s',
|
||||||
:rtype SkydiveClient
|
cfg.CONF.df_skydive.analyzer_endpoint)
|
||||||
"""
|
raise
|
||||||
df_utils.config_parse()
|
|
||||||
nb_api = api_nb.NbApi.get_instance(False, True)
|
|
||||||
return SkydiveClient(nb_api)
|
|
||||||
|
|
||||||
def clear_dragonflow_items(self):
|
def clear_dragonflow_items(self):
|
||||||
"""Delete all the items created by DragonFlow"""
|
"""Delete all the items created by DragonFlow"""
|
||||||
restclient = RESTClient(cfg.CONF.df_skydive.analyzer_endpoint)
|
restclient = RESTClient(cfg.CONF.df_skydive.analyzer_endpoint,
|
||||||
edges = restclient.lookup_edges("G.E().Has('source': 'dragonflow')")
|
username=cfg.CONF.df_skydive.user,
|
||||||
for edge in edges:
|
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(
|
edge_del_msg = skydive_client.WSMessage(
|
||||||
"Graph",
|
"Graph",
|
||||||
skydive_client.EdgeDeletedMsgType,
|
skydive_client.EdgeDeletedMsgType,
|
||||||
edge
|
edge
|
||||||
)
|
)
|
||||||
self.sendWSMessage(edge_del_msg)
|
self.protocol.sendWSMessage(edge_del_msg)
|
||||||
nodes = restclient.lookup_nodes("G.V().Has('source': 'dragonflow')")
|
items = restclient.lookup_nodes("G.V().Has('source', 'dragonflow')")
|
||||||
for node in nodes:
|
for node in items:
|
||||||
node_del_msg = skydive_client.WSMessage(
|
node_del_msg = skydive_client.WSMessage(
|
||||||
"Graph",
|
"Graph",
|
||||||
skydive_client.NodeDeletedMsgType,
|
skydive_client.NodeDeletedMsgType,
|
||||||
node
|
node
|
||||||
)
|
)
|
||||||
self.sendWSMessage(node_del_msg)
|
self.protocol.sendWSMessage(node_del_msg)
|
||||||
|
|
||||||
def start(self):
|
def run(self):
|
||||||
"""Start communication with the SkyDive analyzer
|
"""Start communication with the SkyDive analyzer
|
||||||
|
|
||||||
This starts the operaiton of periodically querying the nb_api and
|
This starts the operaiton of periodically querying the nb_api and
|
||||||
sending all the objects to the SkyDive analyzer.
|
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()
|
self.websocket_client.start()
|
||||||
|
|
||||||
def schedule_stop(self, wait_time):
|
def schedule_stop(self, wait_time):
|
||||||
|
@ -100,10 +94,11 @@ class SkydiveClient(object):
|
||||||
:type wait_time: int
|
:type wait_time: int
|
||||||
"""
|
"""
|
||||||
loop = self.websocket_client.loop
|
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"""
|
"""Stop the process of sending the updates to the SkyDive analyzer"""
|
||||||
|
super(SkydiveClient, self).terminate()
|
||||||
self.websocket_client.stop()
|
self.websocket_client.stop()
|
||||||
|
|
||||||
|
|
||||||
|
@ -280,31 +275,24 @@ class WSClientDragonflowProtocol(skydive_client.WSClientDebugProtocol):
|
||||||
super(WSClientDragonflowProtocol, self).onClose(wasClean, code, reason)
|
super(WSClientDragonflowProtocol, self).onClose(wasClean, code, reason)
|
||||||
|
|
||||||
|
|
||||||
def signal_handler(signal, frame):
|
def start(is_service):
|
||||||
if global_skydive_client:
|
"""main method"""
|
||||||
LOG.info('Stopping SkyDive service')
|
df_config.init(sys.argv)
|
||||||
global_skydive_client.stop()
|
df_utils.config_parse()
|
||||||
|
nb_api = api_nb.NbApi.get_instance(False, True)
|
||||||
|
if is_service:
|
||||||
def set_signal_handler():
|
df_service.register_service('df-skydive-service', nb_api)
|
||||||
signal.signal(signal.SIGINT, signal_handler)
|
service_manager = cotyledon.ServiceManager()
|
||||||
signal.signal(signal.SIGHUP, signal_handler)
|
service_manager.add(SkydiveClient, workers=1, args=(nb_api,))
|
||||||
|
service_manager.run()
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""main method"""
|
start(False)
|
||||||
df_config.init(sys.argv)
|
|
||||||
parser = argparse.ArgumentParser(description='SkyDive integration service')
|
|
||||||
parser.add_argument('-t', '--runtime', type=int,
|
def service_main():
|
||||||
help='Total runtime (default 0 = infinite)')
|
start(True)
|
||||||
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()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -26,9 +26,11 @@ six>=1.10.0 # MIT
|
||||||
httplib2>=0.9.1 # MIT
|
httplib2>=0.9.1 # MIT
|
||||||
WebOb>=1.7.1 # MIT
|
WebOb>=1.7.1 # MIT
|
||||||
jsonmodels>=2.1.3 # BSD License (3 clause)
|
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
|
# These repos are installed from git in OpenStack CI if the job
|
||||||
# configures them as required-projects:
|
# configures them as required-projects:
|
||||||
neutron>=12.0.0 # Apache-2.0
|
neutron>=12.0.0 # Apache-2.0
|
||||||
networking-sfc>=6.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-l3-agent = dragonflow.cmd.eventlet.df_l3_agent:main
|
||||||
df-metadata-service = dragonflow.cmd.eventlet.df_metadata_service:main
|
df-metadata-service = dragonflow.cmd.eventlet.df_metadata_service:main
|
||||||
df-bgp-service = dragonflow.cmd.eventlet.df_bgp_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 =
|
dragonflow.pubsub_driver =
|
||||||
zmq_pubsub_driver = dragonflow.db.pubsub_drivers.zmq_pubsub_driver:ZMQPubSub
|
zmq_pubsub_driver = dragonflow.db.pubsub_drivers.zmq_pubsub_driver:ZMQPubSub
|
||||||
zmq_pubsub_multiproc_driver = dragonflow.db.pubsub_drivers.zmq_pubsub_driver:ZMQPubSubMultiproc
|
zmq_pubsub_multiproc_driver = dragonflow.db.pubsub_drivers.zmq_pubsub_driver:ZMQPubSubMultiproc
|
||||||
|
|
Loading…
Reference in New Issue