| #!/bin/bash |
| # |
| # 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. |
| # |
| |
| # Global Sources |
| # -------------- |
| |
| # There are some ovs functions OVN depends on that must be sourced from |
| # the ovs neutron plugins. |
| source ${TOP_DIR}/lib/neutron_plugins/ovs_base |
| source ${TOP_DIR}/lib/neutron_plugins/openvswitch_agent |
| |
| # Load devstack ovs compliation and loading functions |
| source ${TOP_DIR}/lib/neutron_plugins/ovs_source |
| |
| # Set variables for building OVN from source |
| OVN_REPO=${OVN_REPO:-https://github.com/ovn-org/ovn.git} |
| OVN_REPO_NAME=$(basename ${OVN_REPO} | cut -f1 -d'.') |
| OVN_REPO_NAME=${OVN_REPO_NAME:-ovn} |
| OVN_BRANCH=${OVN_BRANCH:-branch-24.03} |
| # The commit removing OVN bits from the OVS tree, it is the commit that is not |
| # present in OVN tree and is used to distinguish if OVN is part of OVS or not. |
| # https://github.com/openvswitch/ovs/commit/05bf1dbb98b0635a51f75e268ef8aed27601401d |
| OVN_SPLIT_HASH=05bf1dbb98b0635a51f75e268ef8aed27601401d |
| |
| if is_service_enabled tls-proxy; then |
| OVN_PROTO=ssl |
| else |
| OVN_PROTO=tcp |
| fi |
| |
| # How to connect to ovsdb-server hosting the OVN SB database. |
| OVN_SB_REMOTE=${OVN_SB_REMOTE:-$OVN_PROTO:$SERVICE_HOST:6642} |
| |
| # How to connect to ovsdb-server hosting the OVN NB database |
| OVN_NB_REMOTE=${OVN_NB_REMOTE:-$OVN_PROTO:$SERVICE_HOST:6641} |
| |
| # ml2/config for neutron_sync_mode |
| OVN_NEUTRON_SYNC_MODE=${OVN_NEUTRON_SYNC_MODE:-log} |
| |
| # Configured DNS servers to be used with internal_dns extension, only |
| # if the subnet DNS is not configured. |
| OVN_DNS_SERVERS=${OVN_DNS_SERVERS:-8.8.8.8} |
| |
| # The type of OVN L3 Scheduler to use. The OVN L3 Scheduler determines the |
| # hypervisor/chassis where a routers gateway should be hosted in OVN. The |
| # default OVN L3 scheduler is leastloaded |
| OVN_L3_SCHEDULER=${OVN_L3_SCHEDULER:-leastloaded} |
| |
| # A UUID to uniquely identify this system. If one is not specified, a random |
| # one will be generated. A randomly generated UUID will be saved in a file |
| # $OVS_SYSCONFDIR/system-id.conf (typically /etc/openvswitch/system-id.conf) |
| # so that the same one will be re-used if you re-run DevStack or restart |
| # Open vSwitch service. |
| OVN_UUID=${OVN_UUID:-} |
| |
| # Whether or not to build the openvswitch kernel module from ovs. This is required |
| # unless the distro kernel includes ovs+conntrack support. |
| OVN_BUILD_MODULES=$(trueorfalse False OVN_BUILD_MODULES) |
| OVN_BUILD_FROM_SOURCE=$(trueorfalse False OVN_BUILD_FROM_SOURCE) |
| if [[ "$OVN_BUILD_FROM_SOURCE" == "True" ]]; then |
| Q_BUILD_OVS_FROM_GIT=True |
| fi |
| |
| # Whether or not to install the ovs python module from ovs source. This can be |
| # used to test and validate new ovs python features. This should only be used |
| # for development purposes since the ovs python version is controlled by OpenStack |
| # requirements. |
| OVN_INSTALL_OVS_PYTHON_MODULE=$(trueorfalse False OVN_INSTALL_OVS_PYTHON_MODULE) |
| |
| # GENEVE overlay protocol overhead. Defaults to 38 bytes plus the IP version |
| # overhead (20 bytes for IPv4 (default) or 40 bytes for IPv6) which is determined |
| # based on the ML2 overlay_ip_version option. The ML2 framework will use this to |
| # configure the MTU DHCP option. |
| OVN_GENEVE_OVERHEAD=${OVN_GENEVE_OVERHEAD:-38} |
| |
| # The log level of the OVN databases (north and south). |
| # Supported log levels are: off, emer, err, warn, info or dbg. |
| # More information about log levels can be found at |
| # http://www.openvswitch.org/support/dist-docs/ovs-appctl.8.txt |
| OVN_DBS_LOG_LEVEL=${OVN_DBS_LOG_LEVEL:-info} |
| |
| # OVN metadata agent configuration |
| OVN_META_CONF=$NEUTRON_CONF_DIR/neutron_ovn_metadata_agent.ini |
| OVN_META_DATA_HOST=${OVN_META_DATA_HOST:-$(ipv6_unquote $SERVICE_HOST)} |
| |
| # OVN agent configuration |
| OVN_AGENT_CONF=$NEUTRON_CONF_DIR/plugins/ml2/ovn_agent.ini |
| OVN_AGENT_EXTENSIONS=${OVN_AGENT_EXTENSIONS:-} |
| |
| # If True (default) the node will be considered a gateway node. |
| ENABLE_CHASSIS_AS_GW=$(trueorfalse True ENABLE_CHASSIS_AS_GW) |
| OVN_L3_CREATE_PUBLIC_NETWORK=$(trueorfalse True OVN_L3_CREATE_PUBLIC_NETWORK) |
| |
| export OVSDB_SERVER_LOCAL_HOST=$SERVICE_LOCAL_HOST |
| TUNNEL_IP=$TUNNEL_ENDPOINT_IP |
| if [[ "$SERVICE_IP_VERSION" == 6 ]]; then |
| OVSDB_SERVER_LOCAL_HOST=[$OVSDB_SERVER_LOCAL_HOST] |
| TUNNEL_IP=[$TUNNEL_IP] |
| fi |
| |
| OVN_IGMP_SNOOPING_ENABLE=$(trueorfalse False OVN_IGMP_SNOOPING_ENABLE) |
| |
| OVS_PREFIX= |
| if [[ "$OVN_BUILD_FROM_SOURCE" == "True" ]]; then |
| OVS_PREFIX=/usr/local |
| fi |
| OVS_SBINDIR=$OVS_PREFIX/sbin |
| OVS_BINDIR=$OVS_PREFIX/bin |
| OVS_RUNDIR=$OVS_PREFIX/var/run/openvswitch |
| OVS_SHAREDIR=$OVS_PREFIX/share/openvswitch |
| OVS_SCRIPTDIR=$OVS_SHAREDIR/scripts |
| OVS_DATADIR=$DATA_DIR/ovs |
| OVS_SYSCONFDIR=${OVS_SYSCONFDIR:-$OVS_PREFIX/etc/openvswitch} |
| |
| if [[ "$OVN_BUILD_FROM_SOURCE" == "True" ]]; then |
| OVN_DATADIR=$DATA_DIR/ovn |
| else |
| # When using OVN from packages, the data dir for OVN DBs is |
| # /var/lib/ovn |
| OVN_DATADIR=/var/lib/ovn |
| fi |
| OVN_SHAREDIR=$OVS_PREFIX/share/ovn |
| OVN_SCRIPTDIR=$OVN_SHAREDIR/scripts |
| OVN_RUNDIR=$OVS_PREFIX/var/run/ovn |
| |
| NEUTRON_OVN_BIN_DIR=$(get_python_exec_prefix) |
| NEUTRON_OVN_METADATA_BINARY="neutron-ovn-metadata-agent" |
| NEUTRON_OVN_AGENT_BINARY="neutron-ovn-agent" |
| |
| STACK_GROUP="$( id --group --name "$STACK_USER" )" |
| |
| OVN_NORTHD_SERVICE=ovn-northd.service |
| if is_ubuntu; then |
| # The ovn-central.service file on Ubuntu is responsible for starting |
| # ovn-northd and the OVN DBs (on CentOS this is done by ovn-northd.service) |
| OVN_NORTHD_SERVICE=ovn-central.service |
| fi |
| OVSDB_SERVER_SERVICE=ovsdb-server.service |
| OVS_VSWITCHD_SERVICE=ovs-vswitchd.service |
| OVN_CONTROLLER_SERVICE=ovn-controller.service |
| OVN_CONTROLLER_VTEP_SERVICE=ovn-controller-vtep.service |
| if [[ "$OVN_BUILD_FROM_SOURCE" == "True" ]]; then |
| OVSDB_SERVER_SERVICE=devstack@ovsdb-server.service |
| OVS_VSWITCHD_SERVICE=devstack@ovs-vswitchd.service |
| OVN_NORTHD_SERVICE=devstack@ovn-northd.service |
| OVN_CONTROLLER_SERVICE=devstack@ovn-controller.service |
| OVN_CONTROLLER_VTEP_SERVICE=devstack@ovn-controller-vtep.service |
| fi |
| |
| # Defaults Overwrite |
| # ------------------ |
| # NOTE(ralonsoh): during the eventlet removal, the "logger" mech |
| # driver has been removed from this list. Re-add it once the removal |
| # is finished or the mech driver does not call monkey_patch(). |
| Q_ML2_PLUGIN_MECHANISM_DRIVERS=${Q_ML2_PLUGIN_MECHANISM_DRIVERS:-ovn} |
| Q_ML2_PLUGIN_TYPE_DRIVERS=${Q_ML2_PLUGIN_TYPE_DRIVERS:-local,flat,vlan,geneve} |
| Q_ML2_TENANT_NETWORK_TYPE=${Q_ML2_TENANT_NETWORK_TYPE:-"geneve"} |
| Q_ML2_PLUGIN_GENEVE_TYPE_OPTIONS=${Q_ML2_PLUGIN_GENEVE_TYPE_OPTIONS:-"vni_ranges=1:65536"} |
| Q_ML2_PLUGIN_EXT_DRIVERS=${Q_ML2_PLUGIN_EXT_DRIVERS:-port_security,qos} |
| # this one allows empty: |
| ML2_L3_PLUGIN=${ML2_L3_PLUGIN-"ovn-router"} |
| |
| Q_LOG_DRIVER_RATE_LIMIT=${Q_LOG_DRIVER_RATE_LIMIT:-100} |
| Q_LOG_DRIVER_BURST_LIMIT=${Q_LOG_DRIVER_BURST_LIMIT:-25} |
| Q_LOG_DRIVER_LOG_BASE=${Q_LOG_DRIVER_LOG_BASE:-acl_log_meter} |
| |
| # Utility Functions |
| # ----------------- |
| |
| function wait_for_db_file { |
| local count=0 |
| while [ ! -f $1 ]; do |
| sleep 1 |
| count=$((count+1)) |
| if [ "$count" -gt 40 ]; then |
| die $LINENO "DB File $1 not found" |
| fi |
| done |
| } |
| |
| function wait_for_sock_file { |
| local count=0 |
| while [ ! -S $1 ]; do |
| sleep 1 |
| count=$((count+1)) |
| if [ "$count" -gt 40 ]; then |
| die $LINENO "Socket $1 not found" |
| fi |
| done |
| } |
| |
| function use_new_ovn_repository { |
| if [[ "$OVN_BUILD_FROM_SOURCE" == "False" ]]; then |
| return 0 |
| fi |
| if [ -z "$is_new_ovn" ]; then |
| local ovs_repo_dir=$DEST/$OVS_REPO_NAME |
| if [ ! -d $ovs_repo_dir ]; then |
| git_timed clone $OVS_REPO $ovs_repo_dir |
| pushd $ovs_repo_dir |
| git checkout $OVS_BRANCH |
| popd |
| else |
| clone_repository $OVS_REPO $ovs_repo_dir $OVS_BRANCH |
| fi |
| # Check the split commit exists in the current branch |
| pushd $ovs_repo_dir |
| git log $OVS_BRANCH --pretty=format:"%H" | grep -q $OVN_SPLIT_HASH |
| is_new_ovn=$? |
| popd |
| fi |
| return $is_new_ovn |
| } |
| |
| # NOTE(rtheis): Function copied from DevStack _neutron_ovs_base_setup_bridge |
| # and _neutron_ovs_base_add_bridge with the call to neutron-ovs-cleanup |
| # removed. The call is not relevant for OVN, as it is specific to the use |
| # of Neutron's OVS agent and hangs when running stack.sh because |
| # neutron-ovs-cleanup uses the OVSDB native interface. |
| function ovn_base_setup_bridge { |
| local bridge=$1 |
| local addbr_cmd="sudo ovs-vsctl --no-wait -- --may-exist add-br $bridge -- set bridge $bridge protocols=OpenFlow13,OpenFlow15" |
| |
| if [ "$OVS_DATAPATH_TYPE" != "system" ] ; then |
| addbr_cmd="$addbr_cmd -- set Bridge $bridge datapath_type=${OVS_DATAPATH_TYPE}" |
| fi |
| |
| $addbr_cmd |
| sudo ovs-vsctl --no-wait br-set-external-id $bridge bridge-id $bridge |
| } |
| |
| function _start_process { |
| $SYSTEMCTL daemon-reload |
| $SYSTEMCTL enable $1 |
| $SYSTEMCTL restart $1 |
| } |
| |
| function _run_process { |
| local service=$1 |
| local cmd="$2" |
| local stop_cmd="$3" |
| local group=$4 |
| local user=$5 |
| local rundir=${6:-$OVS_RUNDIR} |
| |
| local systemd_service="devstack@$service.service" |
| local unit_file="$SYSTEMD_DIR/$systemd_service" |
| local environment="OVN_RUNDIR=$OVN_RUNDIR OVN_DBDIR=$OVN_DATADIR OVN_LOGDIR=$LOGDIR OVS_RUNDIR=$OVS_RUNDIR OVS_DBDIR=$OVS_DATADIR OVS_LOGDIR=$LOGDIR" |
| |
| echo "Starting $service executed command": $cmd |
| |
| write_user_unit_file $systemd_service "$cmd" "$group" "$user" |
| iniset -sudo $unit_file "Service" "Type" "forking" |
| iniset -sudo $unit_file "Service" "RemainAfterExit" "yes" |
| iniset -sudo $unit_file "Service" "KillMode" "mixed" |
| iniset -sudo $unit_file "Service" "LimitNOFILE" "65536" |
| iniset -sudo $unit_file "Service" "Environment" "$environment" |
| if [ -n "$stop_cmd" ]; then |
| iniset -sudo $unit_file "Service" "ExecStop" "$stop_cmd" |
| fi |
| |
| _start_process $systemd_service |
| |
| local testcmd="test -e $rundir/$service.pid" |
| test_with_retry "$testcmd" "$service did not start" $SERVICE_TIMEOUT 1 |
| local service_ctl_file |
| service_ctl_file=$(ls $rundir | grep $service | grep ctl) |
| if [ -z "$service_ctl_file" ]; then |
| die $LINENO "ctl file for service $service is not present." |
| fi |
| sudo ovs-appctl -t $rundir/$service_ctl_file vlog/set console:off syslog:info file:info |
| } |
| |
| function clone_repository { |
| local repo=$1 |
| local dir=$2 |
| local branch=$3 |
| # Set ERROR_ON_CLONE to false to avoid the need of having the |
| # repositories like OVN and OVS in the required_projects of the job |
| # definition. |
| ERROR_ON_CLONE=false git_clone $repo $dir $branch |
| } |
| |
| function create_public_bridge { |
| # Create the public bridge that OVN will use |
| sudo ovs-vsctl --may-exist add-br $PUBLIC_BRIDGE -- set bridge $PUBLIC_BRIDGE protocols=OpenFlow13,OpenFlow15 |
| sudo ovs-vsctl set open . external-ids:ovn-bridge-mappings=${OVN_BRIDGE_MAPPINGS} |
| _configure_public_network_connectivity |
| } |
| |
| |
| # OVN compilation functions |
| # ------------------------- |
| |
| |
| # compile_ovn() - Compile OVN from source and load needed modules |
| # Accepts three parameters: |
| # - first optional parameter defines prefix for |
| # ovn compilation |
| # - second optional parameter defines localstatedir for |
| # ovn single machine runtime |
| function compile_ovn { |
| local prefix=$1 |
| local localstatedir=$2 |
| |
| if [ -n "$prefix" ]; then |
| prefix="--prefix=$prefix" |
| fi |
| |
| if [ -n "$localstatedir" ]; then |
| localstatedir="--localstatedir=$localstatedir" |
| fi |
| |
| clone_repository $OVN_REPO $DEST/$OVN_REPO_NAME $OVN_BRANCH |
| pushd $DEST/$OVN_REPO_NAME |
| |
| if [ ! -f configure ] ; then |
| ./boot.sh |
| fi |
| |
| # NOTE(mnaser): OVN requires that you build using the OVS from the |
| # submodule. |
| # |
| # https://github.com/ovn-org/ovn/blob/3fb397b63663297acbcbf794e1233951222ae5af/Documentation/intro/install/general.rst#bootstrapping |
| # https://github.com/ovn-org/ovn/issues/128 |
| git submodule update --init |
| pushd ovs |
| if [ ! -f configure ] ; then |
| ./boot.sh |
| fi |
| if [ ! -f config.status ] || [ configure -nt config.status ] ; then |
| ./configure |
| fi |
| make -j$(($(nproc) + 1)) |
| popd |
| |
| if [ ! -f config.status ] || [ configure -nt config.status ] ; then |
| ./configure $prefix $localstatedir |
| fi |
| make -j$(($(nproc) + 1)) |
| sudo make install |
| popd |
| } |
| |
| |
| # OVN Neutron driver functions |
| # ---------------------------- |
| |
| # OVN service sanity check |
| function ovn_sanity_check { |
| if is_service_enabled q-agt neutron-agent; then |
| die $LINENO "The q-agt/neutron-agt service must be disabled with OVN." |
| elif is_service_enabled q-l3 neutron-l3; then |
| die $LINENO "The q-l3/neutron-l3 service must be disabled with OVN." |
| elif is_service_enabled q-svc neutron-api && [[ ! $Q_ML2_PLUGIN_MECHANISM_DRIVERS =~ "ovn" ]]; then |
| die $LINENO "OVN needs to be enabled in \$Q_ML2_PLUGIN_MECHANISM_DRIVERS" |
| elif is_service_enabled q-svc neutron-api && [[ ! $Q_ML2_PLUGIN_TYPE_DRIVERS =~ "geneve" ]]; then |
| die $LINENO "Geneve needs to be enabled in \$Q_ML2_PLUGIN_TYPE_DRIVERS to be used with OVN" |
| fi |
| } |
| |
| # install_ovn() - Collect source and prepare |
| function install_ovn { |
| echo "Installing OVN and dependent packages" |
| |
| # Check the OVN configuration |
| ovn_sanity_check |
| |
| # Install tox, used to generate the config (see devstack/override-defaults) |
| pip_install tox |
| |
| sudo mkdir -p $OVS_RUNDIR |
| sudo chown $(whoami) $OVS_RUNDIR |
| |
| if [[ "$OVN_BUILD_FROM_SOURCE" == "True" ]]; then |
| # If OVS is already installed, remove it, because we're about to |
| # re-install it from source. |
| for package in openvswitch openvswitch-switch openvswitch-common; do |
| if is_package_installed $package ; then |
| uninstall_package $package |
| fi |
| done |
| |
| remove_ovs_packages |
| sudo rm -f $OVS_RUNDIR/* |
| |
| compile_ovs $OVN_BUILD_MODULES |
| if use_new_ovn_repository; then |
| compile_ovn |
| fi |
| |
| sudo mkdir -p $OVS_PREFIX/var/log/openvswitch |
| sudo chown $(whoami) $OVS_PREFIX/var/log/openvswitch |
| sudo mkdir -p $OVS_PREFIX/var/log/ovn |
| sudo chown $(whoami) $OVS_PREFIX/var/log/ovn |
| else |
| # Load fixup_ovn_centos |
| source ${TOP_DIR}/tools/fixup_stuff.sh |
| fixup_ovn_centos |
| install_package $(get_packages openvswitch) |
| install_package $(get_packages ovn) |
| fi |
| |
| # Ensure that the OVS commands are accessible in the PATH |
| export PATH=$OVS_BINDIR:$PATH |
| |
| # Archive log files and create new |
| local log_archive_dir=$LOGDIR/archive |
| mkdir -p $log_archive_dir |
| for logfile in ovs-vswitchd.log ovn-northd.log ovn-controller.log ovn-controller-vtep.log ovs-vtep.log ovsdb-server.log ovsdb-server-nb.log ovsdb-server-sb.log; do |
| if [ -f "$LOGDIR/$logfile" ] ; then |
| mv "$LOGDIR/$logfile" "$log_archive_dir/$logfile.${CURRENT_LOG_TIME}" |
| fi |
| done |
| |
| # Install ovsdbapp from source if requested |
| if use_library_from_git "ovsdbapp"; then |
| git_clone_by_name "ovsdbapp" |
| setup_dev_lib "ovsdbapp" |
| fi |
| |
| # Install ovs python module from ovs source. |
| if [[ "$OVN_INSTALL_OVS_PYTHON_MODULE" == "True" ]]; then |
| sudo pip uninstall -y ovs |
| # Clone the OVS repository if it's not yet present |
| clone_repository $OVS_REPO $DEST/$OVS_REPO_NAME $OVS_BRANCH |
| sudo pip install -e $DEST/$OVS_REPO_NAME/python |
| fi |
| } |
| |
| # filter_network_api_extensions() - Remove non-supported API extensions by |
| # the OVN driver from the list of enabled API extensions |
| function filter_network_api_extensions { |
| SUPPORTED_NETWORK_API_EXTENSIONS=$($PYTHON -c \ |
| 'from neutron.common.ovn import extensions ;\ |
| print(",".join(extensions.ML2_SUPPORTED_API_EXTENSIONS))') |
| SUPPORTED_NETWORK_API_EXTENSIONS=$SUPPORTED_NETWORK_API_EXTENSIONS,$($PYTHON -c \ |
| 'from neutron.common.ovn import extensions ;\ |
| print(",".join(extensions.ML2_SUPPORTED_API_EXTENSIONS_OVN_L3))') |
| if is_service_enabled q-qos neutron-qos ; then |
| SUPPORTED_NETWORK_API_EXTENSIONS="$SUPPORTED_NETWORK_API_EXTENSIONS,qos" |
| fi |
| NETWORK_API_EXTENSIONS=${NETWORK_API_EXTENSIONS:-$SUPPORTED_NETWORK_API_EXTENSIONS} |
| extensions=$(echo $NETWORK_API_EXTENSIONS | tr ', ' '\n' | sort -u) |
| supported_ext=$(echo $SUPPORTED_NETWORK_API_EXTENSIONS | tr ', ' '\n' | sort -u) |
| enabled_ext=$(comm -12 <(echo -e "$extensions") <(echo -e "$supported_ext")) |
| disabled_ext=$(comm -3 <(echo -e "$extensions") <(echo -e "$enabled_ext")) |
| |
| # Log a message in case some extensions had to be disabled because |
| # they are not supported by the OVN driver |
| if [ ! -z "$disabled_ext" ]; then |
| _disabled=$(echo $disabled_ext | tr ' ' ',') |
| echo "The folling network API extensions have been disabled because they are not supported by OVN: $_disabled" |
| fi |
| |
| # Export the final list of extensions that have been enabled and are |
| # supported by OVN |
| export NETWORK_API_EXTENSIONS=$(echo $enabled_ext | tr ' ' ',') |
| } |
| |
| function configure_ovn_plugin { |
| echo "Configuring Neutron for OVN" |
| |
| if is_service_enabled q-svc neutron-api; then |
| filter_network_api_extensions |
| populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2_type_geneve max_header_size=$OVN_GENEVE_OVERHEAD |
| populate_ml2_config /$Q_PLUGIN_CONF_FILE ovn ovn_nb_connection="$OVN_NB_REMOTE" |
| populate_ml2_config /$Q_PLUGIN_CONF_FILE ovn ovn_sb_connection="$OVN_SB_REMOTE" |
| if is_service_enabled tls-proxy; then |
| populate_ml2_config /$Q_PLUGIN_CONF_FILE ovn ovn_sb_ca_cert="$INT_CA_DIR/ca-chain.pem" |
| populate_ml2_config /$Q_PLUGIN_CONF_FILE ovn ovn_sb_certificate="$INT_CA_DIR/$DEVSTACK_CERT_NAME.crt" |
| populate_ml2_config /$Q_PLUGIN_CONF_FILE ovn ovn_sb_private_key="$INT_CA_DIR/private/$DEVSTACK_CERT_NAME.key" |
| populate_ml2_config /$Q_PLUGIN_CONF_FILE ovn ovn_nb_ca_cert="$INT_CA_DIR/ca-chain.pem" |
| populate_ml2_config /$Q_PLUGIN_CONF_FILE ovn ovn_nb_certificate="$INT_CA_DIR/$DEVSTACK_CERT_NAME.crt" |
| populate_ml2_config /$Q_PLUGIN_CONF_FILE ovn ovn_nb_private_key="$INT_CA_DIR/private/$DEVSTACK_CERT_NAME.key" |
| fi |
| populate_ml2_config /$Q_PLUGIN_CONF_FILE ovn neutron_sync_mode="$OVN_NEUTRON_SYNC_MODE" |
| populate_ml2_config /$Q_PLUGIN_CONF_FILE ovn ovn_l3_scheduler="$OVN_L3_SCHEDULER" |
| populate_ml2_config /$Q_PLUGIN_CONF_FILE securitygroup enable_security_group="$Q_USE_SECGROUP" |
| inicomment /$Q_PLUGIN_CONF_FILE securitygroup firewall_driver |
| |
| if is_service_enabled q-log neutron-log; then |
| populate_ml2_config /$Q_PLUGIN_CONF_FILE network_log rate_limit="$Q_LOG_DRIVER_RATE_LIMIT" |
| populate_ml2_config /$Q_PLUGIN_CONF_FILE network_log burst_limit="$Q_LOG_DRIVER_BURST_LIMIT" |
| inicomment /$Q_PLUGIN_CONF_FILE network_log local_output_log_base="$Q_LOG_DRIVER_LOG_BASE" |
| fi |
| |
| if is_service_enabled q-ovn-metadata-agent neutron-ovn-metadata-agent; then |
| populate_ml2_config /$Q_PLUGIN_CONF_FILE ovn ovn_metadata_enabled=True |
| elif is_service_enabled q-ovn-agent neutron-ovn-agent && [[ "$OVN_AGENT_EXTENSIONS" =~ 'metadata' ]]; then |
| populate_ml2_config /$Q_PLUGIN_CONF_FILE ovn ovn_metadata_enabled=True |
| else |
| populate_ml2_config /$Q_PLUGIN_CONF_FILE ovn ovn_metadata_enabled=False |
| fi |
| |
| if is_service_enabled q-dns neutron-dns ; then |
| iniset $NEUTRON_CONF DEFAULT dns_domain openstackgate.local |
| populate_ml2_config /$Q_PLUGIN_CONF_FILE ovn dns_servers="$OVN_DNS_SERVERS" |
| fi |
| |
| iniset $NEUTRON_CONF ovs igmp_snooping_enable $OVN_IGMP_SNOOPING_ENABLE |
| fi |
| |
| if is_service_enabled q-dhcp neutron-dhcp ; then |
| iniset $NEUTRON_CONF DEFAULT dhcp_agent_notification True |
| else |
| iniset $NEUTRON_CONF DEFAULT dhcp_agent_notification False |
| fi |
| |
| if is_service_enabled n-api-meta ; then |
| if is_service_enabled q-ovn-metadata-agent neutron-ovn-metadata-agent; then |
| iniset $NOVA_CONF neutron service_metadata_proxy True |
| elif is_service_enabled q-ovn-agent neutron-ovn-agent && [[ "$OVN_AGENT_EXTENSIONS" =~ 'metadata' ]]; then |
| iniset $NOVA_CONF neutron service_metadata_proxy True |
| fi |
| fi |
| } |
| |
| function configure_ovn { |
| echo "Configuring OVN" |
| |
| if [ -z "$OVN_UUID" ] ; then |
| if [ -f $OVS_SYSCONFDIR/system-id.conf ]; then |
| OVN_UUID=$(cat $OVS_SYSCONFDIR/system-id.conf) |
| else |
| OVN_UUID=$(uuidgen) |
| echo $OVN_UUID | sudo tee $OVS_SYSCONFDIR/system-id.conf |
| fi |
| else |
| local ovs_uuid |
| ovs_uuid=$(cat $OVS_SYSCONFDIR/system-id.conf) |
| if [ "$ovs_uuid" != $OVN_UUID ]; then |
| echo $OVN_UUID | sudo tee $OVS_SYSCONFDIR/system-id.conf |
| fi |
| fi |
| |
| # Erase the pre-set configurations from packages. DevStack will |
| # configure OVS and OVN accordingly for its use. |
| if [[ "$OVN_BUILD_FROM_SOURCE" == "False" ]] && is_fedora; then |
| sudo truncate -s 0 /etc/openvswitch/default.conf |
| sudo truncate -s 0 /etc/sysconfig/openvswitch |
| sudo truncate -s 0 /etc/sysconfig/ovn |
| fi |
| |
| # Metadata |
| local sample_file="" |
| local config_file="" |
| if is_service_enabled q-ovn-agent neutron-ovn-agent && [[ "$OVN_AGENT_EXTENSIONS" =~ 'metadata' ]] && is_service_enabled ovn-controller; then |
| sample_file=$NEUTRON_DIR/etc/neutron/plugins/ml2/ovn_agent.ini.sample |
| config_file=$OVN_AGENT_CONF |
| elif is_service_enabled q-ovn-metadata-agent neutron-ovn-metadata-agent && is_service_enabled ovn-controller; then |
| sample_file=$NEUTRON_DIR/etc/neutron_ovn_metadata_agent.ini.sample |
| config_file=$OVN_META_CONF |
| fi |
| if [ -n "$config_file" ]; then |
| sudo install -d -o $STACK_USER $NEUTRON_CONF_DIR |
| |
| mkdir -p $NEUTRON_DIR/etc/neutron/plugins/ml2 |
| (cd $NEUTRON_DIR && exec ./tools/generate_config_file_samples.sh) |
| |
| cp $sample_file $config_file |
| configure_root_helper_options $config_file |
| |
| iniset $config_file DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL |
| iniset $config_file DEFAULT nova_metadata_host $OVN_META_DATA_HOST |
| iniset $config_file DEFAULT metadata_workers $API_WORKERS |
| iniset $config_file DEFAULT state_path $DATA_DIR/neutron |
| iniset $config_file ovs ovsdb_connection tcp:$OVSDB_SERVER_LOCAL_HOST:6640 |
| iniset $config_file ovn ovn_sb_connection $OVN_SB_REMOTE |
| if is_service_enabled tls-proxy; then |
| iniset $config_file ovn \ |
| ovn_sb_ca_cert $INT_CA_DIR/ca-chain.pem |
| iniset $config_file ovn \ |
| ovn_sb_certificate $INT_CA_DIR/$DEVSTACK_CERT_NAME.crt |
| iniset $config_file ovn \ |
| ovn_sb_private_key $INT_CA_DIR/private/$DEVSTACK_CERT_NAME.key |
| fi |
| if [[ $config_file == $OVN_AGENT_CONF ]]; then |
| iniset $config_file agent extensions $OVN_AGENT_EXTENSIONS |
| iniset $config_file ovn ovn_nb_connection $OVN_NB_REMOTE |
| fi |
| fi |
| } |
| |
| function init_ovn { |
| # clean up from previous (possibly aborted) runs |
| # create required data files |
| |
| # Assumption: this is a dedicated test system and there is nothing important |
| # in the ovn, ovn-nb, or ovs databases. We're going to trash them and |
| # create new ones on each devstack run. |
| |
| local mkdir_cmd="mkdir -p ${OVN_DATADIR}" |
| |
| if [[ "$OVN_BUILD_FROM_SOURCE" == "False" ]]; then |
| mkdir_cmd="sudo ${mkdir_cmd}" |
| fi |
| |
| $mkdir_cmd |
| mkdir -p $OVS_DATADIR |
| |
| rm -f $OVS_DATADIR/*.db |
| rm -f $OVS_DATADIR/.*.db.~lock~ |
| sudo rm -f $OVN_DATADIR/*.db |
| sudo rm -f $OVN_DATADIR/.*.db.~lock~ |
| sudo rm -f $OVN_RUNDIR/*.sock |
| } |
| |
| function _start_ovs { |
| echo "Starting OVS" |
| if is_service_enabled ovn-controller ovn-controller-vtep ovn-northd; then |
| # ovsdb-server and ovs-vswitchd are used privately in OVN as openvswitch service names. |
| enable_service ovsdb-server |
| enable_service ovs-vswitchd |
| |
| if [[ "$OVN_BUILD_FROM_SOURCE" == "True" ]]; then |
| if [ ! -f $OVS_DATADIR/conf.db ]; then |
| ovsdb-tool create $OVS_DATADIR/conf.db $OVS_SHAREDIR/vswitch.ovsschema |
| fi |
| |
| if is_service_enabled ovn-controller-vtep; then |
| if [ ! -f $OVS_DATADIR/vtep.db ]; then |
| ovsdb-tool create $OVS_DATADIR/vtep.db $OVS_SHAREDIR/vtep.ovsschema |
| fi |
| fi |
| |
| local dbcmd="$OVS_SBINDIR/ovsdb-server --remote=punix:$OVS_RUNDIR/db.sock --remote=ptcp:6640:$OVSDB_SERVER_LOCAL_HOST --pidfile --detach --log-file" |
| dbcmd+=" --remote=db:Open_vSwitch,Open_vSwitch,manager_options" |
| if is_service_enabled ovn-controller-vtep; then |
| dbcmd+=" --remote=db:hardware_vtep,Global,managers $OVS_DATADIR/vtep.db" |
| fi |
| dbcmd+=" $OVS_DATADIR/conf.db" |
| _run_process ovsdb-server "$dbcmd" "" "$STACK_GROUP" "root" "$OVS_RUNDIR" |
| |
| # Note: ovn-controller will create and configure br-int once it is started. |
| # So, no need to create it now because nothing depends on that bridge here. |
| local ovscmd="$OVS_SBINDIR/ovs-vswitchd --log-file --pidfile --detach" |
| _run_process ovs-vswitchd "$ovscmd" "" "$STACK_GROUP" "root" "$OVS_RUNDIR" |
| else |
| _start_process "$OVSDB_SERVER_SERVICE" |
| _start_process "$OVS_VSWITCHD_SERVICE" |
| fi |
| |
| echo "Configuring OVSDB" |
| if is_service_enabled tls-proxy; then |
| sudo ovs-vsctl --no-wait set-ssl \ |
| $INT_CA_DIR/private/$DEVSTACK_CERT_NAME.key \ |
| $INT_CA_DIR/$DEVSTACK_CERT_NAME.crt \ |
| $INT_CA_DIR/ca-chain.pem |
| fi |
| |
| sudo ovs-vsctl --no-wait set-manager ptcp:6640:$OVSDB_SERVER_LOCAL_HOST |
| sudo ovs-vsctl --no-wait set open_vswitch . system-type="devstack" |
| sudo ovs-vsctl --no-wait set open_vswitch . external-ids:system-id="$OVN_UUID" |
| sudo ovs-vsctl --no-wait set open_vswitch . external-ids:ovn-remote="$OVN_SB_REMOTE" |
| sudo ovs-vsctl --no-wait set open_vswitch . external-ids:ovn-bridge="br-int" |
| sudo ovs-vsctl --no-wait set open_vswitch . external-ids:ovn-encap-type="geneve" |
| sudo ovs-vsctl --no-wait set open_vswitch . external-ids:ovn-encap-ip="$TUNNEL_IP" |
| sudo ovs-vsctl --no-wait set open_vswitch . external-ids:hostname=$(hostname) |
| # Select this chassis to host gateway routers |
| if [[ "$ENABLE_CHASSIS_AS_GW" == "True" ]]; then |
| sudo ovs-vsctl --no-wait set open_vswitch . external-ids:ovn-cms-options="enable-chassis-as-gw" |
| fi |
| |
| if is_provider_network || [[ $Q_USE_PROVIDERNET_FOR_PUBLIC == "True" ]]; then |
| ovn_base_setup_bridge $OVS_PHYSICAL_BRIDGE |
| sudo ovs-vsctl set open . external-ids:ovn-bridge-mappings=${PHYSICAL_NETWORK}:${OVS_PHYSICAL_BRIDGE} |
| fi |
| |
| if is_service_enabled ovn-controller-vtep ; then |
| ovn_base_setup_bridge br-v |
| vtep-ctl add-ps br-v |
| vtep-ctl set Physical_Switch br-v tunnel_ips=$TUNNEL_IP |
| |
| enable_service ovs-vtep |
| local vtepcmd="$OVS_SCRIPTDIR/ovs-vtep --log-file --pidfile --detach br-v" |
| _run_process ovs-vtep "$vtepcmd" "" "$STACK_GROUP" "root" "$OVS_RUNDIR" |
| |
| vtep-ctl set-manager tcp:$HOST_IP:6640 |
| fi |
| fi |
| } |
| |
| function _wait_for_ovn_and_set_custom_config { |
| # Wait for the service to be ready |
| # Check for socket and db files for both OVN NB and SB |
| wait_for_sock_file $OVN_RUNDIR/ovnnb_db.sock |
| wait_for_sock_file $OVN_RUNDIR/ovnsb_db.sock |
| wait_for_db_file $OVN_DATADIR/ovnnb_db.db |
| wait_for_db_file $OVN_DATADIR/ovnsb_db.db |
| |
| if is_service_enabled tls-proxy; then |
| sudo ovn-nbctl --db=unix:$OVN_RUNDIR/ovnnb_db.sock set-ssl $INT_CA_DIR/private/$DEVSTACK_CERT_NAME.key $INT_CA_DIR/$DEVSTACK_CERT_NAME.crt $INT_CA_DIR/ca-chain.pem |
| sudo ovn-sbctl --db=unix:$OVN_RUNDIR/ovnsb_db.sock set-ssl $INT_CA_DIR/private/$DEVSTACK_CERT_NAME.key $INT_CA_DIR/$DEVSTACK_CERT_NAME.crt $INT_CA_DIR/ca-chain.pem |
| fi |
| |
| sudo ovn-nbctl --db=unix:$OVN_RUNDIR/ovnnb_db.sock set-connection p${OVN_PROTO}:6641:$SERVICE_LISTEN_ADDRESS -- set connection . inactivity_probe=60000 |
| sudo ovn-sbctl --db=unix:$OVN_RUNDIR/ovnsb_db.sock set-connection p${OVN_PROTO}:6642:$SERVICE_LISTEN_ADDRESS -- set connection . inactivity_probe=60000 |
| sudo ovs-appctl -t $OVN_RUNDIR/ovnnb_db.ctl vlog/set console:off syslog:$OVN_DBS_LOG_LEVEL file:$OVN_DBS_LOG_LEVEL |
| sudo ovs-appctl -t $OVN_RUNDIR/ovnsb_db.ctl vlog/set console:off syslog:$OVN_DBS_LOG_LEVEL file:$OVN_DBS_LOG_LEVEL |
| } |
| |
| # start_ovn() - Start running processes, including screen |
| function start_ovn { |
| echo "Starting OVN" |
| |
| _start_ovs |
| |
| local SCRIPTDIR=$OVN_SCRIPTDIR |
| if ! use_new_ovn_repository; then |
| SCRIPTDIR=$OVS_SCRIPTDIR |
| fi |
| |
| if is_service_enabled ovn-northd ; then |
| if [[ "$OVN_BUILD_FROM_SOURCE" == "True" ]]; then |
| local cmd="/bin/bash $SCRIPTDIR/ovn-ctl --no-monitor start_northd" |
| local stop_cmd="/bin/bash $SCRIPTDIR/ovn-ctl stop_northd" |
| |
| _run_process ovn-northd "$cmd" "$stop_cmd" "$STACK_GROUP" "root" "$OVN_RUNDIR" |
| else |
| _start_process "$OVN_NORTHD_SERVICE" |
| fi |
| |
| _wait_for_ovn_and_set_custom_config |
| |
| fi |
| |
| if is_service_enabled ovn-controller ; then |
| if [[ "$OVN_BUILD_FROM_SOURCE" == "True" ]]; then |
| local cmd="/bin/bash $SCRIPTDIR/ovn-ctl --no-monitor start_controller" |
| local stop_cmd="/bin/bash $SCRIPTDIR/ovn-ctl stop_controller" |
| |
| _run_process ovn-controller "$cmd" "$stop_cmd" "$STACK_GROUP" "root" "$OVN_RUNDIR" |
| else |
| _start_process "$OVN_CONTROLLER_SERVICE" |
| fi |
| fi |
| |
| if is_service_enabled ovn-controller-vtep ; then |
| if [[ "$OVN_BUILD_FROM_SOURCE" == "True" ]]; then |
| local cmd="$OVS_BINDIR/ovn-controller-vtep --log-file --pidfile --detach --ovnsb-db=$OVN_SB_REMOTE" |
| _run_process ovn-controller-vtep "$cmd" "" "$STACK_GROUP" "root" "$OVN_RUNDIR" |
| else |
| _start_process "$OVN_CONTROLLER_VTEP_SERVICE" |
| fi |
| fi |
| |
| if is_service_enabled q-ovn-metadata-agent neutron-ovn-metadata-agent; then |
| run_process q-ovn-metadata-agent "$NEUTRON_OVN_BIN_DIR/$NEUTRON_OVN_METADATA_BINARY --config-file $OVN_META_CONF" |
| # Format logging |
| setup_logging $OVN_META_CONF |
| fi |
| |
| if is_service_enabled q-ovn-agent neutron-ovn-agent; then |
| run_process q-ovn-agent "$NEUTRON_OVN_BIN_DIR/$NEUTRON_OVN_AGENT_BINARY --config-file $OVN_AGENT_CONF" |
| # Format logging |
| setup_logging $OVN_AGENT_CONF |
| fi |
| } |
| |
| function _stop_ovs_dp { |
| sudo ovs-dpctl dump-dps | sudo xargs -n1 ovs-dpctl del-dp |
| modprobe -q -r vport_geneve vport_vxlan openvswitch || true |
| } |
| |
| function _stop_process { |
| local service=$1 |
| echo "Stopping process $service" |
| if $SYSTEMCTL is-enabled $service; then |
| $SYSTEMCTL stop $service |
| $SYSTEMCTL disable $service |
| fi |
| } |
| |
| function stop_ovn { |
| if is_service_enabled q-ovn-metadata-agent neutron-ovn-metadata-agent; then |
| # pkill takes care not to kill itself, but it may kill its parent |
| # sudo unless we use the "ps | grep [f]oo" trick |
| sudo pkill -9 -f "[h]aproxy" || : |
| _stop_process "devstack@q-ovn-metadata-agent.service" |
| fi |
| if is_service_enabled q-ovn-agent neutron-ovn-agent; then |
| # pkill takes care not to kill itself, but it may kill its parent |
| # sudo unless we use the "ps | grep [f]oo" trick |
| sudo pkill -9 -f "[h]aproxy" || : |
| _stop_process "devstack@q-ovn-agent.service" |
| fi |
| if is_service_enabled ovn-controller-vtep ; then |
| _stop_process "$OVN_CONTROLLER_VTEP_SERVICE" |
| fi |
| if is_service_enabled ovn-controller ; then |
| _stop_process "$OVN_CONTROLLER_SERVICE" |
| fi |
| if is_service_enabled ovn-northd ; then |
| _stop_process "$OVN_NORTHD_SERVICE" |
| fi |
| if is_service_enabled ovs-vtep ; then |
| _stop_process "devstack@ovs-vtep.service" |
| fi |
| |
| _stop_process "$OVS_VSWITCHD_SERVICE" |
| _stop_process "$OVSDB_SERVER_SERVICE" |
| |
| _stop_ovs_dp |
| } |
| |
| function _cleanup { |
| local path=${1:-$DEST/$OVN_REPO_NAME} |
| pushd $path |
| cd $path |
| sudo make uninstall |
| sudo make distclean |
| popd |
| } |
| |
| # cleanup_ovn() - Remove residual data files, anything left over from previous |
| # runs that a clean run would need to clean up |
| function cleanup_ovn { |
| local ovn_path=$DEST/$OVN_REPO_NAME |
| local ovs_path=$DEST/$OVS_REPO_NAME |
| |
| if [ -d $ovn_path ]; then |
| _cleanup $ovn_path |
| fi |
| |
| if [ -d $ovs_path ]; then |
| _cleanup $ovs_path |
| fi |
| |
| sudo rm -rf $OVN_RUNDIR |
| } |