Adds GW type/class (both BGP and static uplinks)
Change-Id: I52a6cce14566469d67c07fd488972a245bc7b73f
This commit is contained in:
		
							
								
								
									
										369
									
								
								files/gateway/functions
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										369
									
								
								files/gateway/functions
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,369 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Copyright 2016 Midokura SARL
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Useful common functions are defined here.  Some of them were shamelessly
 | 
				
			||||||
 | 
					# stolen from devstack.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Save trace setting
 | 
				
			||||||
 | 
					XTRACE=$(set +o | grep xtrace)
 | 
				
			||||||
 | 
					set +o xtrace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Control Functions
 | 
				
			||||||
 | 
					# -----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Prints line number and "message" in warning format
 | 
				
			||||||
 | 
					# warn $LINENO "message"
 | 
				
			||||||
 | 
					function warn {
 | 
				
			||||||
 | 
					    local exitcode=$?
 | 
				
			||||||
 | 
					    local xtrace=$(set +o | grep xtrace)
 | 
				
			||||||
 | 
					    set +o xtrace
 | 
				
			||||||
 | 
					    local msg="[WARNING] ${BASH_SOURCE[2]}:$1 $2"
 | 
				
			||||||
 | 
					    echo $msg 1>&2;
 | 
				
			||||||
 | 
					    if [[ -n ${LOGDIR} ]]; then
 | 
				
			||||||
 | 
					        echo $msg >> "${LOGDIR}/error.log"
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					    $xtrace
 | 
				
			||||||
 | 
					    return $exitcode
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Prints backtrace info
 | 
				
			||||||
 | 
					# filename:lineno:function
 | 
				
			||||||
 | 
					# backtrace level
 | 
				
			||||||
 | 
					function backtrace {
 | 
				
			||||||
 | 
					    local level=$1
 | 
				
			||||||
 | 
					    local deep=$((${#BASH_SOURCE[@]} - 1))
 | 
				
			||||||
 | 
					    echo "[Call Trace]"
 | 
				
			||||||
 | 
					    while [ $level -le $deep ]; do
 | 
				
			||||||
 | 
					        echo "${BASH_SOURCE[$deep]}:${BASH_LINENO[$deep-1]}:${FUNCNAME[$deep-1]}"
 | 
				
			||||||
 | 
					        deep=$((deep - 1))
 | 
				
			||||||
 | 
					    done
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Prints line number and "message" in error format
 | 
				
			||||||
 | 
					# err $LINENO "message"
 | 
				
			||||||
 | 
					function err {
 | 
				
			||||||
 | 
					    local exitcode=$?
 | 
				
			||||||
 | 
					    local xtrace=$(set +o | grep xtrace)
 | 
				
			||||||
 | 
					    set +o xtrace
 | 
				
			||||||
 | 
					    local msg="[ERROR] ${BASH_SOURCE[2]}:$1 $2"
 | 
				
			||||||
 | 
					    echo $msg 1>&2;
 | 
				
			||||||
 | 
					    if [[ -n ${LOGDIR} ]]; then
 | 
				
			||||||
 | 
					        echo $msg >> "${LOGDIR}/error.log"
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					    $xtrace
 | 
				
			||||||
 | 
					    return $exitcode
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Prints line number and "message" then exits
 | 
				
			||||||
 | 
					# die $LINENO "message"
 | 
				
			||||||
 | 
					function die {
 | 
				
			||||||
 | 
					    local exitcode=$?
 | 
				
			||||||
 | 
					    set +o xtrace
 | 
				
			||||||
 | 
					    local line=$1; shift
 | 
				
			||||||
 | 
					    if [ $exitcode == 0 ]; then
 | 
				
			||||||
 | 
					        exitcode=1
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					    backtrace 2
 | 
				
			||||||
 | 
					    err $line "$*"
 | 
				
			||||||
 | 
					    # Give buffers a second to flush
 | 
				
			||||||
 | 
					    sleep 1
 | 
				
			||||||
 | 
					    exit $exitcode
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Checks an environment variable is not set or has length 0 OR if the
 | 
				
			||||||
 | 
					# exit code is non-zero and prints "message" and exits
 | 
				
			||||||
 | 
					# NOTE: env-var is the variable name without a '$'
 | 
				
			||||||
 | 
					# die_if_not_set $LINENO env-var "message"
 | 
				
			||||||
 | 
					function die_if_not_set {
 | 
				
			||||||
 | 
					    local exitcode=$?
 | 
				
			||||||
 | 
					    local xtrace=$(set +o | grep xtrace)
 | 
				
			||||||
 | 
					    set +o xtrace
 | 
				
			||||||
 | 
					    local line=$1; shift
 | 
				
			||||||
 | 
					    local evar=$1; shift
 | 
				
			||||||
 | 
					    if ! is_set $evar || [ $exitcode != 0 ]; then
 | 
				
			||||||
 | 
					        die $line "$*"
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					    $xtrace
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Test if the named environment variable is set and not zero length
 | 
				
			||||||
 | 
					# is_set env-var
 | 
				
			||||||
 | 
					function is_set {
 | 
				
			||||||
 | 
					    local var=\$"$1"
 | 
				
			||||||
 | 
					    eval "[ -n \"$var\" ]" # For ex.: sh -c "[ -n \"$var\" ]" would be better, but several exercises depends on this
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Package Functions
 | 
				
			||||||
 | 
					# -----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Wrapper for ``apt-get``
 | 
				
			||||||
 | 
					# apt_get operation package [package ...]
 | 
				
			||||||
 | 
					function apt_get {
 | 
				
			||||||
 | 
					    sudo DEBIAN_FRONTEND=noninteractive \
 | 
				
			||||||
 | 
					        apt-get --option "Dpkg::Options::=--force-confnew" --assume-yes "$@"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Update package repository
 | 
				
			||||||
 | 
					# Uses globals ``NO_UPDATE_REPOS``, ``REPOS_UPDATED``, ``RETRY_UPDATE``
 | 
				
			||||||
 | 
					# install_package package [package ...]
 | 
				
			||||||
 | 
					function update_package_repo {
 | 
				
			||||||
 | 
					    NO_UPDATE_REPOS=${NO_UPDATE_REPOS:-False}
 | 
				
			||||||
 | 
					    REPOS_UPDATED=${REPOS_UPDATED:-False}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if [[ "$NO_UPDATE_REPOS" = "True" ]]; then
 | 
				
			||||||
 | 
					        return 0
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    local xtrace=$(set +o | grep xtrace)
 | 
				
			||||||
 | 
					    set +o xtrace
 | 
				
			||||||
 | 
					    if [[ "$REPOS_UPDATED" != "True" ]]; then
 | 
				
			||||||
 | 
					        # if there are transient errors pulling the updates, that's fine.
 | 
				
			||||||
 | 
					        # It may be secondary repositories that we don't really care about.
 | 
				
			||||||
 | 
					        apt_get update  || /bin/true
 | 
				
			||||||
 | 
					        REPOS_UPDATED=True
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					    $xtrace
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Package installer
 | 
				
			||||||
 | 
					# install_package package [package ...]
 | 
				
			||||||
 | 
					function install_package {
 | 
				
			||||||
 | 
					    update_package_repo
 | 
				
			||||||
 | 
					    apt_get install --no-install-recommends "$@"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Function to tell if a package is installed
 | 
				
			||||||
 | 
					# is_package_installed package [package ...]
 | 
				
			||||||
 | 
					function is_package_installed {
 | 
				
			||||||
 | 
					    dpkg -s "$@" > /dev/null 2> /dev/null
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# System Functions
 | 
				
			||||||
 | 
					# -----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Service wrapper to stop services
 | 
				
			||||||
 | 
					# stop_service service-name
 | 
				
			||||||
 | 
					# Checks if kmod is loaded
 | 
				
			||||||
 | 
					function is_kmod_loaded {
 | 
				
			||||||
 | 
					    lsmod | grep -w $1 >& /dev/null
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Process Functions
 | 
				
			||||||
 | 
					# -----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function is_screen_running {
 | 
				
			||||||
 | 
					    type -p screen > /dev/null && screen -ls | egrep -q "[0-9]\.$1"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function create_screen {
 | 
				
			||||||
 | 
					    local name=$1
 | 
				
			||||||
 | 
					    screen -d -m -S $name -t shell -s /bin/bash
 | 
				
			||||||
 | 
					    sleep 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Set a reasonable status bar
 | 
				
			||||||
 | 
					    SCREEN_HARDSTATUS='%{= .} %-Lw%{= .}%> %n%f %t*%{= .}%+Lw%< %-=%{g}(%{d}%H/%l%{g})'
 | 
				
			||||||
 | 
					    screen -r $name -X hardstatus alwayslastline "$SCREEN_HARDSTATUS"
 | 
				
			||||||
 | 
					    screen -r $name -X setenv PROMPT_COMMAND /bin/true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Helper to launch a process in a named screen
 | 
				
			||||||
 | 
					# Uses globals ``CURRENT_LOG_TIME``, ``LOGDIR``,
 | 
				
			||||||
 | 
					# ``SERVICE_DIR``
 | 
				
			||||||
 | 
					# screen_process name "command-line"
 | 
				
			||||||
 | 
					# Run a command in a shell in a screen window
 | 
				
			||||||
 | 
					function screen_process {
 | 
				
			||||||
 | 
					    local name=$1
 | 
				
			||||||
 | 
					    local command="$2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SERVICE_DIR=${SERVICE_DIR:-/tmp/status}
 | 
				
			||||||
 | 
					    mkdir -p ${SERVICE_DIR}/${SCREEN_NAME}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Append the process to the screen rc file
 | 
				
			||||||
 | 
					    screen_rc ${SCREEN_NAME} "$name" "$command"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    screen -S ${SCREEN_NAME} -X screen -t $name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if [[ -n ${LOGDIR} ]]; then
 | 
				
			||||||
 | 
					        screen -S ${SCREEN_NAME} -p $name -X logfile ${LOGDIR}/${name}.log.${CURRENT_LOG_TIME}
 | 
				
			||||||
 | 
					        screen -S ${SCREEN_NAME} -p $name -X log on
 | 
				
			||||||
 | 
					        ln -sf ${LOGDIR}/${name}.log.${CURRENT_LOG_TIME} ${LOGDIR}/${name}.log
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # sleep to allow bash to be ready to be send the command - we are
 | 
				
			||||||
 | 
					    # creating a new window in screen and then sends characters, so if
 | 
				
			||||||
 | 
					    # bash isn't running by the time we send the command, nothing happens
 | 
				
			||||||
 | 
					    sleep 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    NL=`echo -ne '\015'`
 | 
				
			||||||
 | 
					    screen -S ${SCREEN_NAME} -p $name -X stuff "$command & echo \$! >$SERVICE_DIR/${SCREEN_NAME}/${name}.pid; fg || echo \"$name failed to start\" | tee \"$SERVICE_DIR/${SCREEN_NAME}/${name}.failure\"$NL"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# _run_process() is designed to be backgrounded by run_process() to simulate a
 | 
				
			||||||
 | 
					# fork.  It includes the dirty work of closing extra filehandles and preparing log
 | 
				
			||||||
 | 
					# files to produce the same logs as screen_it().  The log filename is derived
 | 
				
			||||||
 | 
					# from the service name.
 | 
				
			||||||
 | 
					# _run_process service "command-line"
 | 
				
			||||||
 | 
					function _run_process {
 | 
				
			||||||
 | 
					    local service=$1
 | 
				
			||||||
 | 
					    local command="$2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Undo logging redirections and close the extra descriptors
 | 
				
			||||||
 | 
					    exec 1>&3
 | 
				
			||||||
 | 
					    exec 2>&3
 | 
				
			||||||
 | 
					    exec 3>&-
 | 
				
			||||||
 | 
					    exec 6>&-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    local real_logfile="${LOGDIR}/${service}.log.${CURRENT_LOG_TIME}"
 | 
				
			||||||
 | 
					    if [[ -n ${LOGDIR} ]]; then
 | 
				
			||||||
 | 
					        exec 1>&"$real_logfile" 2>&1
 | 
				
			||||||
 | 
					        ln -sf "$real_logfile" ${LOGDIR}/${service}.log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Hack to get stdout from the Python interpreter for the logs.
 | 
				
			||||||
 | 
					        export PYTHONUNBUFFERED=1
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SERVICE_DIR=${SERVICE_DIR:-/tmp/status}
 | 
				
			||||||
 | 
					    mkdir -p ${SERVICE_DIR}/${SCREEN_NAME}
 | 
				
			||||||
 | 
					    setsid $command & echo $! > ${SERVICE_DIR}/${SCREEN_NAME}/${service}.pid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Just silently exit this process
 | 
				
			||||||
 | 
					    exit 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Run a single service under screen or directly
 | 
				
			||||||
 | 
					# If the command includes shell metachatacters (;<>*) it must be run using a shell
 | 
				
			||||||
 | 
					# run_process service "command-line"
 | 
				
			||||||
 | 
					function run_process {
 | 
				
			||||||
 | 
					    local service=$1
 | 
				
			||||||
 | 
					    local command="$2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if [[ "$USE_SCREEN" = "True" ]]; then
 | 
				
			||||||
 | 
					        screen_process "$service" "cd $TOP_DIR && $command"
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        # Spawn directly without screen
 | 
				
			||||||
 | 
					        cd $TOP_DIR
 | 
				
			||||||
 | 
					        _run_process "$service" "$command" &
 | 
				
			||||||
 | 
					        cd -
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Screen rc file builder
 | 
				
			||||||
 | 
					# Uses globals ``SCREENRC``
 | 
				
			||||||
 | 
					# screen_rc service "command-line"
 | 
				
			||||||
 | 
					function screen_rc {
 | 
				
			||||||
 | 
					    local screen=$1
 | 
				
			||||||
 | 
					    SCREENRC=$DEVMIDO_DIR/$screen-screenrc
 | 
				
			||||||
 | 
					    if [[ ! -e $SCREENRC ]]; then
 | 
				
			||||||
 | 
					        # Name the screen session
 | 
				
			||||||
 | 
					        echo "sessionname $screen" > $SCREENRC
 | 
				
			||||||
 | 
					        # Set a reasonable statusbar
 | 
				
			||||||
 | 
					        echo "hardstatus alwayslastline '$SCREEN_HARDSTATUS'" >> $SCREENRC
 | 
				
			||||||
 | 
					        # Some distributions override PROMPT_COMMAND for the screen terminal type - turn that off
 | 
				
			||||||
 | 
					        echo "setenv PROMPT_COMMAND /bin/true" >> $SCREENRC
 | 
				
			||||||
 | 
					        echo "screen -t shell bash" >> $SCREENRC
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					    # If this service doesn't already exist in the screenrc file
 | 
				
			||||||
 | 
					    if ! grep $1 $SCREENRC 2>&1 > /dev/null; then
 | 
				
			||||||
 | 
					        NL=`echo -ne '\015'`
 | 
				
			||||||
 | 
					        echo "screen -t $1 bash" >> $SCREENRC
 | 
				
			||||||
 | 
					        echo "stuff \"$2$NL\"" >> $SCREENRC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if [[ -n ${LOGDIR} ]]; then
 | 
				
			||||||
 | 
					            echo "logfile ${LOGDIR}/${1}.log.${CURRENT_LOG_TIME}" >>$SCREENRC
 | 
				
			||||||
 | 
					            echo "log on" >>$SCREENRC
 | 
				
			||||||
 | 
					        fi
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Set an option in an INI file
 | 
				
			||||||
 | 
					# iniset config-file section option value
 | 
				
			||||||
 | 
					function iniset {
 | 
				
			||||||
 | 
					    local xtrace=$(set +o | grep xtrace)
 | 
				
			||||||
 | 
					    set +o xtrace
 | 
				
			||||||
 | 
					    local file=$1
 | 
				
			||||||
 | 
					    local section=$2
 | 
				
			||||||
 | 
					    local option=$3
 | 
				
			||||||
 | 
					    local value=$4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [[ -z $section || -z $option ]] && return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ! grep -q "^\[$section\]" "$file" 2>/dev/null; then
 | 
				
			||||||
 | 
					        # Add section at the end
 | 
				
			||||||
 | 
					        echo -e "\n[$section]" >>"$file"
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					    if ! ini_has_option "$file" "$section" "$option"; then
 | 
				
			||||||
 | 
					        # Add it
 | 
				
			||||||
 | 
					        sed -i -e "/^\[$section\]/ a\\
 | 
				
			||||||
 | 
					$option = $value
 | 
				
			||||||
 | 
					" "$file"
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        local sep=$(echo -ne "\x01")
 | 
				
			||||||
 | 
					        # Replace it
 | 
				
			||||||
 | 
					        sed -i -e '/^\['${section}'\]/,/^\[.*\]/ s'${sep}'^\('${option}'[ \t]*=[ \t]*\).*$'${sep}'\1'"${value}"${sep} "$file"
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					    $xtrace
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Determinate is the given option present in the INI file
 | 
				
			||||||
 | 
					# ini_has_option config-file section option
 | 
				
			||||||
 | 
					function ini_has_option {
 | 
				
			||||||
 | 
					    local xtrace=$(set +o | grep xtrace)
 | 
				
			||||||
 | 
					    set +o xtrace
 | 
				
			||||||
 | 
					    local file=$1
 | 
				
			||||||
 | 
					    local section=$2
 | 
				
			||||||
 | 
					    local option=$3
 | 
				
			||||||
 | 
					    local line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    line=$(sed -ne "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ p; }" "$file")
 | 
				
			||||||
 | 
					    $xtrace
 | 
				
			||||||
 | 
					    [ -n "$line" ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function stop_process {
 | 
				
			||||||
 | 
					    local service=$1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Kill via pid if we have one available
 | 
				
			||||||
 | 
					    pkill -F $SERVICE_DIR/$SCREEN_NAME/$service.pid
 | 
				
			||||||
 | 
					    rm $SERVICE_DIR/$SCREEN_NAME/$service.pid
 | 
				
			||||||
 | 
					    screen -S $SCREEN_NAME -p $service -X kill
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# MN Functions
 | 
				
			||||||
 | 
					# ------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Wrapper for mn-conf command
 | 
				
			||||||
 | 
					# Uses globals ``ZOOKEEPER_HOSTS``
 | 
				
			||||||
 | 
					function configure_mn {
 | 
				
			||||||
 | 
					    local value="$2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # quote with "" only when necessary.  we don't always quote because
 | 
				
			||||||
 | 
					    # mn-conf complains for quoted booleans.  eg. "false"
 | 
				
			||||||
 | 
					    if [[ "${value}" =~ ":" || "${value}" = "" ]]; then
 | 
				
			||||||
 | 
					        value="\"${value}\""
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # In some commands, mn-conf creates a local file, which requires root
 | 
				
			||||||
 | 
					    # access.  For simplicity, always call mn-conf with root for now.
 | 
				
			||||||
 | 
					    echo $1 : "${value}" | MIDO_ZOOKEEPER_HOSTS="$ZOOKEEPER_HOSTS" sudo mn-conf set
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Restore xtrace
 | 
				
			||||||
 | 
					$XTRACE
 | 
				
			||||||
@@ -1,309 +0,0 @@
 | 
				
			|||||||
if RUBY_VERSION == '1.8.7'
 | 
					 | 
				
			||||||
    require 'rubygems'
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
require 'uri'
 | 
					 | 
				
			||||||
require 'faraday'
 | 
					 | 
				
			||||||
require 'json'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Puppet::Type.type(:midonet_gateway).provide(:midonet_api_caller) do
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def create
 | 
					 | 
				
			||||||
    define_connection(resource[:midonet_api_url])
 | 
					 | 
				
			||||||
    # For each remote BGP peer, create a virtual port on
 | 
					 | 
				
			||||||
    # the MidoNet Provider Router that is going to be used
 | 
					 | 
				
			||||||
    # for the BGP communication. Connection to midonet api
 | 
					 | 
				
			||||||
    # is assumed
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    router_id = call_get_provider_router()[0]['id']
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    message = Hash.new
 | 
					 | 
				
			||||||
    message['portAddress'] = resource[:bgp_port]["port_address"]
 | 
					 | 
				
			||||||
    message['networkAddress'] = resource[:bgp_port]["net_prefix"]
 | 
					 | 
				
			||||||
    message['networkLength'] = resource[:bgp_port]["net_length"].to_i
 | 
					 | 
				
			||||||
    message['type'] = "Router"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    port = call_create_uplink_port(router_id, message)
 | 
					 | 
				
			||||||
    port_id = port[0]['id']
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Configure BGP on the virtual ports. Port is
 | 
					 | 
				
			||||||
    # assumed created
 | 
					 | 
				
			||||||
    remote_peers = resource[:remote_peers]
 | 
					 | 
				
			||||||
    if remote_peers.class == Hash
 | 
					 | 
				
			||||||
       remote_peers = [remote_peers]
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    remote_peers.each do |rp|
 | 
					 | 
				
			||||||
      message = Hash.new
 | 
					 | 
				
			||||||
      message['localAS'] = resource[:local_as]
 | 
					 | 
				
			||||||
      message['peerAS'] = rp["as"]
 | 
					 | 
				
			||||||
      message['peerAddr'] = rp["ip"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      call_add_bgp_to_port(port_id, message)
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Add route for 'MidoNet Provider Router' uplink port
 | 
					 | 
				
			||||||
    message = Hash.new
 | 
					 | 
				
			||||||
    message['type'] = "Normal"
 | 
					 | 
				
			||||||
    message['srcNetworkAddr'] = "0.0.0.0"
 | 
					 | 
				
			||||||
    message['srcNetworkLength'] = 0
 | 
					 | 
				
			||||||
    message['dstNetworkAddr'] = resource[:bgp_port]["net_prefix"]
 | 
					 | 
				
			||||||
    message['dstNetworkLength'] = resource[:bgp_port]["net_length"].to_i
 | 
					 | 
				
			||||||
    message['weight'] = 100
 | 
					 | 
				
			||||||
    message['nextHopPort'] = port_id
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    call_add_route_for_uplink_port(router_id, message)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # In order to provide external connectivity for hosted
 | 
					 | 
				
			||||||
    # virtual machines, the floating IP network has to be
 | 
					 | 
				
			||||||
    # advertised to the BGP peers. BGP connection is assumed created
 | 
					 | 
				
			||||||
    bgp_connections = call_get_bgp_connections(port_id)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #TODO(carmela): make this modification more elegant... or whatever
 | 
					 | 
				
			||||||
    advertise_networks = resource[:advertise_net]
 | 
					 | 
				
			||||||
    if advertise_networks.class == Hash
 | 
					 | 
				
			||||||
       advertise_networks = [advertise_networks]
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    bgp_connections.each do |bgp_c|
 | 
					 | 
				
			||||||
      advertise_networks.each do |net|
 | 
					 | 
				
			||||||
        message = Hash.new
 | 
					 | 
				
			||||||
        message['nwPrefix'] = net["net_prefix"]
 | 
					 | 
				
			||||||
        message['prefixLength'] = net["net_length"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        bgp_id = bgp_c["id"]
 | 
					 | 
				
			||||||
        call_advertise_route_to_bgp(bgp_id, message)
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Bind the MidoNet Provider Router’s virtual ports to
 | 
					 | 
				
			||||||
    # the physical network interfaces on the Gateway Nodes.
 | 
					 | 
				
			||||||
    # Host and port are assumed created. Interface name should
 | 
					 | 
				
			||||||
    # be an string
 | 
					 | 
				
			||||||
    host_id = call_get_host()[0]['id']
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    message = Hash.new
 | 
					 | 
				
			||||||
    message['interfaceName'] = resource[:interface]
 | 
					 | 
				
			||||||
    message['portId'] = port_id
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    call_bind_port_to_interface(host_id, message)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Configure a stateful port group
 | 
					 | 
				
			||||||
    spg = call_get_stateful_port_group()
 | 
					 | 
				
			||||||
    if spg.empty?
 | 
					 | 
				
			||||||
      message = Hash.new
 | 
					 | 
				
			||||||
      message['name'] = "uplink-spg"
 | 
					 | 
				
			||||||
      message['stateful'] = "true"
 | 
					 | 
				
			||||||
      message['tenantId'] = call_get_tenant()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      spg = call_create_stateful_port_group(message)
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Add the ports to the port group
 | 
					 | 
				
			||||||
    message = Hash.new
 | 
					 | 
				
			||||||
    message['portId'] = port_id
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    call_add_ports_to_port_group(spg[0]["id"], message)
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def destroy
 | 
					 | 
				
			||||||
    define_connection(resource[:midonet_api_url])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    router_id = call_get_provider_router()[0]['id']
 | 
					 | 
				
			||||||
    port_address = resource[:bgp_port]['port_address']
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    port = call_get_uplink_port(router_id, port_address)
 | 
					 | 
				
			||||||
    port_id = port[0]["id"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Delete the stateful port group
 | 
					 | 
				
			||||||
    #    TODO(carmela): delete only in case is the last port on the port group
 | 
					 | 
				
			||||||
    #    port_group_id = call_get_stateful_port_group()[0]['id']
 | 
					 | 
				
			||||||
    #    call_delete_stateful_port_group(port_group_id)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Delete uplink port
 | 
					 | 
				
			||||||
    call_delete_uplink_port(port_id)
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def exists?
 | 
					 | 
				
			||||||
    define_connection(resource[:midonet_api_url])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    router = call_get_provider_router()
 | 
					 | 
				
			||||||
    if router.empty?
 | 
					 | 
				
			||||||
      raise 'MidoNet Provider Router does not exist. We cannot create uplink ports'
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    host = call_get_host()
 | 
					 | 
				
			||||||
    if host.empty?
 | 
					 | 
				
			||||||
      raise 'There is no MidoNet agent running on this host'
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    uplink_port = call_get_uplink_port(router[0]['id'], resource[:bgp_port]['port_address'])
 | 
					 | 
				
			||||||
    if uplink_port.empty?
 | 
					 | 
				
			||||||
      return false
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return true
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def define_connection(url)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @connection = Faraday.new(:url => url,
 | 
					 | 
				
			||||||
                              :ssl => { :verify =>false }) do |builder|
 | 
					 | 
				
			||||||
        builder.request(:retry, {
 | 
					 | 
				
			||||||
          :max        => 5,
 | 
					 | 
				
			||||||
          :interval   => 0.05,
 | 
					 | 
				
			||||||
          :exceptions => [
 | 
					 | 
				
			||||||
            Faraday::Error::TimeoutError,
 | 
					 | 
				
			||||||
            Faraday::ConnectionFailed,
 | 
					 | 
				
			||||||
            Errno::ETIMEDOUT,
 | 
					 | 
				
			||||||
            'Timeout::Error',
 | 
					 | 
				
			||||||
          ],
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
        builder.request(:basic_auth, resource[:username], resource[:password])
 | 
					 | 
				
			||||||
        builder.adapter(:net_http)
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @connection.headers['X-Auth-Token'] = call_get_token()
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def call_get_token()
 | 
					 | 
				
			||||||
    res = @connection.get do |req|
 | 
					 | 
				
			||||||
      req.url "/midonet-api/login"
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    return JSON.parse(res.body)['key']
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def call_get_tenant()
 | 
					 | 
				
			||||||
    res = @connection.get do |req|
 | 
					 | 
				
			||||||
      req.url "/midonet-api/tenants"
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    return JSON.parse(res.body)[0]['id']
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def call_get_provider_router()
 | 
					 | 
				
			||||||
    res = @connection.get do |req|
 | 
					 | 
				
			||||||
      req.url "/midonet-api/routers"
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    output = JSON.parse(res.body)
 | 
					 | 
				
			||||||
    return output.select { |name| name['name'] == resource[:router]}
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def call_get_stateful_port_group()
 | 
					 | 
				
			||||||
    res = @connection.get do |req|
 | 
					 | 
				
			||||||
      req.url "/midonet-api/port_groups"
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    output = JSON.parse(res.body)
 | 
					 | 
				
			||||||
    return output.select { |name| name['name'] == 'uplink-spg'}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def call_get_uplink_port(router_id, port_address)
 | 
					 | 
				
			||||||
    res = @connection.get do |req|
 | 
					 | 
				
			||||||
      req.url "/midonet-api/routers/#{router_id}/ports"
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    output =  JSON.parse(res.body)
 | 
					 | 
				
			||||||
    return output.select { |port| port['portAddress'] == port_address }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def call_get_host()
 | 
					 | 
				
			||||||
    res = @connection.get do |req|
 | 
					 | 
				
			||||||
      req.url "/midonet-api/hosts"
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    output = JSON.parse(res.body)
 | 
					 | 
				
			||||||
    return output.select{ |host| host['name'] == resource[:hostname].to_s }
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def call_create_uplink_port(router_id, message)
 | 
					 | 
				
			||||||
    res = @connection.post do |req|
 | 
					 | 
				
			||||||
      req.url "/midonet-api/routers/#{router_id}/ports"
 | 
					 | 
				
			||||||
      req.headers['Content-Type'] = "application/vnd.org.midonet.Port-v2+json"
 | 
					 | 
				
			||||||
      req.body = message.to_json
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    return call_get_uplink_port(router_id, message["portAddress"])
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def call_delete_uplink_port(port_id)
 | 
					 | 
				
			||||||
    res = @connection.delete do |req|
 | 
					 | 
				
			||||||
      req.url "/midonet-api/ports/#{port_id}"
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def call_add_bgp_to_port(port_id, message)
 | 
					 | 
				
			||||||
    res = @connection.post do |req|
 | 
					 | 
				
			||||||
      req.url "/midonet-api/ports/#{port_id}/bgps"
 | 
					 | 
				
			||||||
      req.headers['Content-Type'] = "application/vnd.org.midonet.Bgp-v1+json"
 | 
					 | 
				
			||||||
      req.body = message.to_json
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def call_add_route_for_uplink_port(router_id, message)
 | 
					 | 
				
			||||||
    res = @connection.post do |req|
 | 
					 | 
				
			||||||
      req.url "/midonet-api/routers/#{router_id}/routes"
 | 
					 | 
				
			||||||
      req.headers['Content-Type'] = "application/vnd.org.midonet.Route-v1+json"
 | 
					 | 
				
			||||||
      req.body = message.to_json
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def call_get_bgp_connections(port_id)
 | 
					 | 
				
			||||||
    res = @connection.get do |req|
 | 
					 | 
				
			||||||
      req.url "/midonet-api/ports/#{port_id}/bgps"
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    output = JSON.parse(res.body)
 | 
					 | 
				
			||||||
    return output
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def call_advertise_route_to_bgp(bgp_id, message)
 | 
					 | 
				
			||||||
    res = @connection.post do |req|
 | 
					 | 
				
			||||||
      req.url "/midonet-api/bgps/#{bgp_id}/ad_routes"
 | 
					 | 
				
			||||||
      req.headers['Content-Type'] = "application/vnd.org.midonet.AdRoute-v1+json"
 | 
					 | 
				
			||||||
      req.body = message.to_json
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def call_bind_port_to_interface(host_id, message)
 | 
					 | 
				
			||||||
    res = @connection.post do |req|
 | 
					 | 
				
			||||||
      req.url "/midonet-api/hosts/#{host_id}/ports"
 | 
					 | 
				
			||||||
      req.headers['Content-Type'] = "application/vnd.org.midonet.HostInterfacePort-v1+json"
 | 
					 | 
				
			||||||
      req.body = message.to_json
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def call_create_stateful_port_group(message)
 | 
					 | 
				
			||||||
    res = @connection.post do |req|
 | 
					 | 
				
			||||||
      req.url "/midonet-api/port_groups"
 | 
					 | 
				
			||||||
      req.headers['Content-Type'] = "application/vnd.org.midonet.PortGroup-v1+json"
 | 
					 | 
				
			||||||
      req.body = message.to_json
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    return call_get_stateful_port_group()
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def call_add_ports_to_port_group(port_group_id, message)
 | 
					 | 
				
			||||||
    res = @connection.post do |req|
 | 
					 | 
				
			||||||
      req.url "/midonet-api/port_groups/#{port_group_id}/ports"
 | 
					 | 
				
			||||||
      req.headers['Content-Type'] = "application/vnd.org.midonet.PortGroupPort-v1+json"
 | 
					 | 
				
			||||||
      req.body = message.to_json
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def call_delete_stateful_port_group(port_group_id)
 | 
					 | 
				
			||||||
    res = @connection.delete do |req|
 | 
					 | 
				
			||||||
      req.url "/midonet-api/port_groups/#{port_group_id}"
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  private :call_add_bgp_to_port
 | 
					 | 
				
			||||||
          :call_add_ports_to_port_group
 | 
					 | 
				
			||||||
          :call_add_route_for_uplink_port
 | 
					 | 
				
			||||||
          :call_advertise_route_to_bgp
 | 
					 | 
				
			||||||
          :call_bind_port_to_interface
 | 
					 | 
				
			||||||
          :call_create_stateful_port_group
 | 
					 | 
				
			||||||
          :call_create_uplink_port
 | 
					 | 
				
			||||||
          :call_delete_stateful_port_group
 | 
					 | 
				
			||||||
          :call_delete_uplink_port
 | 
					 | 
				
			||||||
          :call_get_bgp_connections
 | 
					 | 
				
			||||||
          :call_get_host
 | 
					 | 
				
			||||||
          :call_get_stateful_port_group
 | 
					 | 
				
			||||||
          :call_get_provider_router
 | 
					 | 
				
			||||||
          :call_get_tenant
 | 
					 | 
				
			||||||
          :call_get_uplink_port
 | 
					 | 
				
			||||||
          :define_connection
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
							
								
								
									
										217
									
								
								lib/puppet/provider/midonet_gateway_bgp/midonet_api_caller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								lib/puppet/provider/midonet_gateway_bgp/midonet_api_caller.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,217 @@
 | 
				
			|||||||
 | 
					if RUBY_VERSION == '1.8.7'
 | 
				
			||||||
 | 
					    require 'rubygems'
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require 'uri'
 | 
				
			||||||
 | 
					require 'faraday'
 | 
				
			||||||
 | 
					require 'json'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Puppet::Type.type(:midonet_gateway_bgp).provide(:midonet_api_caller) do
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def create
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    define_connection(resource[:midonet_api_url])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Get the edge router uuid
 | 
				
			||||||
 | 
					    provider_router = call_get_provider_router()[0]
 | 
				
			||||||
 | 
					    provider_router_id = provider_router['id']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Assign local ASN to the provider router
 | 
				
			||||||
 | 
					    asn = provider_router['asNumber']
 | 
				
			||||||
 | 
					    call_assign_asn(provider_router_id, resource[:bgp_local_as_number]) unless asn == resource[:bgp_local_as_number]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Sync BGP peers
 | 
				
			||||||
 | 
					    bgp_neighbors = call_get_bgp_peers(provider_router_id)
 | 
				
			||||||
 | 
					    m = Array.new
 | 
				
			||||||
 | 
					    bgp_neighbors.each do |bgp_neighbor|
 | 
				
			||||||
 | 
					      n = { "ip_address" => bgp_neighbor["address"],
 | 
				
			||||||
 | 
					        "remote_asn" => bgp_neighbor["asNumber"] }
 | 
				
			||||||
 | 
					      m << n
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    tbd_peers = m - resource[:bgp_neighbors]
 | 
				
			||||||
 | 
					    tba_peers = resource[:bgp_neighbors] - m
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tba_peers.each { |a| call_add_bgp_peer(provider_router_id, a['ip_address'], a['remote_asn']) }
 | 
				
			||||||
 | 
					    tbd_peers.each do |d|
 | 
				
			||||||
 | 
					      bgp_peer_id = bgp_neighbors.select { |bgp_neighbor| bgp_neighbor['asNumber'] == d['remote_asn'] }[0]["id"]
 | 
				
			||||||
 | 
					      call_delete_bgp_peer(bgp_peer_id)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Advertise floating IP networks
 | 
				
			||||||
 | 
					    bgp_advertised_networks = call_get_bgp_networks(provider_router_id)
 | 
				
			||||||
 | 
					    j = Array.new
 | 
				
			||||||
 | 
					    bgp_advertised_networks.each do |bgp_advertised_network|
 | 
				
			||||||
 | 
					      k = [ bgp_advertised_network["subnetAddress"], bgp_advertised_network["subnetLength"] ].join("/")
 | 
				
			||||||
 | 
					      j << k
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    tbd_bgp_networks = j - resource[:bgp_advertised_networks]
 | 
				
			||||||
 | 
					    tba_bgp_networks = resource[:bgp_advertised_networks] - j
 | 
				
			||||||
 | 
					    tba_bgp_networks.each { |a| call_advertise_bgp_network(provider_router_id, a) }
 | 
				
			||||||
 | 
					    tbd_bgp_networks.each do |d|
 | 
				
			||||||
 | 
					      bgp_network_id = bgp_advertised_networks.select { |bgp_advertised_network| bgp_advertised_network['subnetAddress'] == d.split("/")[0] && bgp_advertised_network['subnetLength'] == d.split("/")[1] }[0]["id"]
 | 
				
			||||||
 | 
					      call_delete_bgp_network(provider_router_id, bgp_network_id)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def destroy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    define_connection(resource[:midonet_api_url])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Get the edge router uuid
 | 
				
			||||||
 | 
					    provider_router_id = call_get_provider_router()[0]['id']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # "Unset" asNumber by setting it to -1 (default value)
 | 
				
			||||||
 | 
					    call_assign_asn(provider_router_id, "-1")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Remove BGP peers from router
 | 
				
			||||||
 | 
					    bgp_peers = call_get_bgp_peers(provider_router_id)
 | 
				
			||||||
 | 
					    bgp_peers.each do |bgp_peer|
 | 
				
			||||||
 | 
					      call_delete_bgp_peer(bgp_peer["id"])
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # De-advertise floating IP networks
 | 
				
			||||||
 | 
					    bgp_networks = call_get_bgp_networks(provider_router_id)
 | 
				
			||||||
 | 
					    bgp_networks.each do |bgp_network|
 | 
				
			||||||
 | 
					      call_delete_bgp_network(bgp_network)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def exists?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    define_connection(resource[:midonet_api_url])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Get the edge router uuid
 | 
				
			||||||
 | 
					    provider_router = call_get_provider_router()[0]
 | 
				
			||||||
 | 
					    provider_router_id = provider_router['id']
 | 
				
			||||||
 | 
					    result_array = Array.new
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Check if local ASN is the same
 | 
				
			||||||
 | 
					    result_array.push(provider_router["asNumber"] == resource[:bgp_local_as_number])
 | 
				
			||||||
 | 
					    # Check if BGP neighbors are the same
 | 
				
			||||||
 | 
					    bgp_neighbors = call_get_bgp_peers(provider_router_id)
 | 
				
			||||||
 | 
					    m = Array.new
 | 
				
			||||||
 | 
					    bgp_neighbors.each do |bgp_neighbor|
 | 
				
			||||||
 | 
					      n = { "ip_address" => bgp_neighbor["address"],
 | 
				
			||||||
 | 
					        "remote_asn" => bgp_neighbor["asNumber"] }
 | 
				
			||||||
 | 
					      m << n
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    result_array.push(m == resource[:bgp_neighbors])
 | 
				
			||||||
 | 
					    # Check if advertised networks are the same
 | 
				
			||||||
 | 
					    bgp_advertised_networks = call_get_bgp_networks(provider_router_id)
 | 
				
			||||||
 | 
					    j = Array.new
 | 
				
			||||||
 | 
					    bgp_advertised_networks.each do |bgp_advertised_network|
 | 
				
			||||||
 | 
					      k = [ bgp_advertised_network["subnetAddress"], bgp_advertised_network["subnetLength"] ].join("/")
 | 
				
			||||||
 | 
					      j << k
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    result_array.push(j == resource[:bgp_advertised_networks])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Test if all tests are positive
 | 
				
			||||||
 | 
					    return result_array.uniq == [true]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def define_connection(url)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @connection = Faraday.new(:url => url,
 | 
				
			||||||
 | 
					                              :ssl => { :verify =>false }) do |builder|
 | 
				
			||||||
 | 
					        builder.request(:retry, {
 | 
				
			||||||
 | 
					          :max        => 5,
 | 
				
			||||||
 | 
					          :interval   => 0.05,
 | 
				
			||||||
 | 
					          :exceptions => [
 | 
				
			||||||
 | 
					            Faraday::Error::TimeoutError,
 | 
				
			||||||
 | 
					            Faraday::ConnectionFailed,
 | 
				
			||||||
 | 
					            Errno::ETIMEDOUT,
 | 
				
			||||||
 | 
					            'Timeout::Error',
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        builder.request(:basic_auth, resource[:username], resource[:password])
 | 
				
			||||||
 | 
					        builder.adapter(:net_http)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @connection.headers['X-Auth-Token'] = call_get_token()
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def call_get_token()
 | 
				
			||||||
 | 
					    res = @connection.get do |req|
 | 
				
			||||||
 | 
					      req.url "/midonet-api/login"
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    return JSON.parse(res.body)['key']
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def call_get_provider_router()
 | 
				
			||||||
 | 
					    res = @connection.get do |req|
 | 
				
			||||||
 | 
					      req.url "/midonet-api/routers"
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    output = JSON.parse(res.body)
 | 
				
			||||||
 | 
					    provider_router = output.select { |r| r['name'] == resource[:router]}
 | 
				
			||||||
 | 
					    raise "Router #{resource[:router]} does not exist" if provider_router.empty?
 | 
				
			||||||
 | 
					    return provider_router
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def call_assign_asn( provider_router_id, bgp_local_as_number )
 | 
				
			||||||
 | 
					    res = @connection.post do |req|
 | 
				
			||||||
 | 
					      req.url "/midonet-api/routers"
 | 
				
			||||||
 | 
					      req.headers['Content-Type'] = "application/vnd.org.midonet.Router-v3+json"
 | 
				
			||||||
 | 
					      req.body = { 'id' => provider_router_id,
 | 
				
			||||||
 | 
					                   'asNumber' => bgp_local_as_number }.to_json
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def call_add_bgp_peer( provider_router_id, ip_address, remote_asn )
 | 
				
			||||||
 | 
					    res = @connection.post do |req|
 | 
				
			||||||
 | 
					      req.url "/midonet-api/#{provider_router_id}/bgp_peers"
 | 
				
			||||||
 | 
					      req.headers['Content-Type'] = "application/vnd.org.midonet.BgpPeer-v1+json"
 | 
				
			||||||
 | 
					      req.body = { 'address' => ip_address,
 | 
				
			||||||
 | 
					                   'asNumber' => remote_asn }.to_json
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def call_advertise_bgp_network( provider_router_id, bgp_advertised_network )
 | 
				
			||||||
 | 
					    subnet_address, subnet_length = bgp_advertised_network.split("/")
 | 
				
			||||||
 | 
					    res = @connection.post do |req|
 | 
				
			||||||
 | 
					      req.url "/midonet-api/#{provider_router_id}/bgp_networks"
 | 
				
			||||||
 | 
					      req.headers['Content-Type'] = "application/vnd.org.midonet.BgpNetwork-v1+json"
 | 
				
			||||||
 | 
					      req.body = { 'subnetAddress' => subnet_address,
 | 
				
			||||||
 | 
					                   'subnetLength'  => subnet_length }.to_json
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def call_delete_bgp_peer(bgp_peer_id)
 | 
				
			||||||
 | 
					    res = @connection.delete do |req|
 | 
				
			||||||
 | 
					      req.url "/midonet-api/bgp_peers/#{bgp_peer_id}"
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def call_delete_bgp_network(bgp_network)
 | 
				
			||||||
 | 
					    res = @connection.delete do |req|
 | 
				
			||||||
 | 
					      req.url "/midonet-api/bgp_networks/#{bgp_network}"
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def call_get_bgp_peers(provider_router_id)
 | 
				
			||||||
 | 
					    res = @connection.get do |req|
 | 
				
			||||||
 | 
					      req.url "/midonet-api/routers/#{provider_router_id}/bgp_peers"
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    output = JSON.parse(res.body)
 | 
				
			||||||
 | 
					    return output
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def call_get_bgp_networks(provider_router_id)
 | 
				
			||||||
 | 
					    res = @connection.get do |req|
 | 
				
			||||||
 | 
					      req.url "/midonet-api/routers/#{provider_router_id}/bgp_networks"
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    output = JSON.parse(res.body)
 | 
				
			||||||
 | 
					    return output.map { |e| e["id"] }
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private :call_get_provider_router
 | 
				
			||||||
 | 
					          :define_connection
 | 
				
			||||||
 | 
					          :call_assign_asn
 | 
				
			||||||
 | 
					          :call_add_bgp_peer
 | 
				
			||||||
 | 
					          :call_get_bgp_networks
 | 
				
			||||||
 | 
					          :call_get_bgp_peers
 | 
				
			||||||
 | 
					          :call_delete_bgp_network
 | 
				
			||||||
 | 
					          :call_delete_bgp_peer
 | 
				
			||||||
 | 
					          :call_advertise_bgp_network
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@@ -1,159 +0,0 @@
 | 
				
			|||||||
require 'uri'
 | 
					 | 
				
			||||||
require 'facter'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Puppet::Type.newtype(:midonet_gateway) do
 | 
					 | 
				
			||||||
  @doc = %q{BGP Uplink Configuration
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      Example:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        midonet_gateway {'hostname':
 | 
					 | 
				
			||||||
           midonet_api_url => 'http://controller:8080',
 | 
					 | 
				
			||||||
           username        => 'admin',
 | 
					 | 
				
			||||||
           password        => 'admin',
 | 
					 | 
				
			||||||
           tenant_name     => 'admin',
 | 
					 | 
				
			||||||
           interface       => 'eth1',
 | 
					 | 
				
			||||||
           local_as        => '64512',
 | 
					 | 
				
			||||||
           bgp_port        => { 'port_address' => '198.51.100.2', 'net_prefix' => '198.51.100.0', 'net_length' => '30'},
 | 
					 | 
				
			||||||
           remote_peers    => [ { 'as' => '64513', 'ip' => '198.51.100.1' },
 | 
					 | 
				
			||||||
                                    { 'as' => '64513', 'ip' => '203.0.113.1' } ],
 | 
					 | 
				
			||||||
           advertise_net   => [ { 'net_prefix' => '192.0.2.0', 'net_length' => '24' } ]
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  ensurable
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  autorequire(:package) do ['midolman'] end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  newparam(:hostname, :namevar => true) do
 | 
					 | 
				
			||||||
    desc 'Hostname of the host that will act as gateway in a MidoNet managed cloud'
 | 
					 | 
				
			||||||
    # Regex obtained from StackOverflow question:
 | 
					 | 
				
			||||||
    # http://stackoverflow.com/questions/1418423/the-hostname-regex
 | 
					 | 
				
			||||||
    validate do |value|
 | 
					 | 
				
			||||||
      unless value =~ /^(?=.{1,255}$)[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?)*\.?$/
 | 
					 | 
				
			||||||
        raise ArgumentError, "'%s' is not a valid hostname" % value
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  newparam(:midonet_api_url) do
 | 
					 | 
				
			||||||
    desc 'MidoNet API endpoint to connect to'
 | 
					 | 
				
			||||||
    validate do |value|
 | 
					 | 
				
			||||||
      unless value =~ /\A#{URI::regexp(['http', 'https'])}\z/
 | 
					 | 
				
			||||||
        raise ArgumentError, "'%s' is not a valid URI" % value
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  newparam(:username) do
 | 
					 | 
				
			||||||
    desc 'Username of the admin user in keystone'
 | 
					 | 
				
			||||||
    defaultto 'admin'
 | 
					 | 
				
			||||||
    validate do |value|
 | 
					 | 
				
			||||||
      unless value =~ /\w+$/
 | 
					 | 
				
			||||||
        raise ArgumentError, "'%s' is not a valid username" % value
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  newparam(:password) do
 | 
					 | 
				
			||||||
    desc 'Password of the admin user in keystone'
 | 
					 | 
				
			||||||
    defaultto 'admin'
 | 
					 | 
				
			||||||
    validate do |value|
 | 
					 | 
				
			||||||
      unless value =~ /\w+$/
 | 
					 | 
				
			||||||
        raise ArgumentError, "'%s' is not a valid password" % value
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  newparam(:tenant_name) do
 | 
					 | 
				
			||||||
    desc 'Tenant name of the admin user'
 | 
					 | 
				
			||||||
    defaultto 'admin'
 | 
					 | 
				
			||||||
    validate do |value|
 | 
					 | 
				
			||||||
      unless value =~ /\w+$/
 | 
					 | 
				
			||||||
        raise ArgumentError, "'%s' is not a tenant name" % value
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  newparam(:interface) do
 | 
					 | 
				
			||||||
    desc "Physical interface where the MidoNet Provider Router's port is binded to"
 | 
					 | 
				
			||||||
    defaultto 'eth0'
 | 
					 | 
				
			||||||
    validate do |value|
 | 
					 | 
				
			||||||
      unless value =~ /^\w+(.\d+)?$/
 | 
					 | 
				
			||||||
        raise ArgumentError, "'%s' is not a valid interface" % value
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  newparam(:local_as) do
 | 
					 | 
				
			||||||
    desc "Local AS number"
 | 
					 | 
				
			||||||
    validate do |value|
 | 
					 | 
				
			||||||
      unless value =~ /\d+/
 | 
					 | 
				
			||||||
        raise ArgumentError, "'%s' is not a valid AS" % value
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  newparam(:remote_peers) do
 | 
					 | 
				
			||||||
    desc "#to be filled"
 | 
					 | 
				
			||||||
    defaultto []
 | 
					 | 
				
			||||||
    validate do |value|
 | 
					 | 
				
			||||||
      if value.class == Hash
 | 
					 | 
				
			||||||
        value = [value]
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
      value.each do |rp|
 | 
					 | 
				
			||||||
        unless rp["as"] =~ /\d+/
 | 
					 | 
				
			||||||
          raise ArgumentError, "'%s' is not a valid AS name" % rp["as"]
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
        unless rp["ip"] =~ /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/
 | 
					 | 
				
			||||||
          raise ArgumentError, "'%s' is not a valid IP address" % rp["ip"]
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  newparam(:bgp_port) do
 | 
					 | 
				
			||||||
    desc "#to be filled"
 | 
					 | 
				
			||||||
    validate do |value|
 | 
					 | 
				
			||||||
      [:port_address, :net_prefix, :net_length].all? {|key| value.key? key}
 | 
					 | 
				
			||||||
      unless value["port_address"] =~ /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/
 | 
					 | 
				
			||||||
        raise ArgumentError, "'%s' is not a valid IP address" % value["port_address"]
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
      unless value["net_prefix"] =~ /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/
 | 
					 | 
				
			||||||
        raise ArgumentError, "'%s' is not a valid IPv4 network address" % value["net_prefix"]
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
      unless value["net_length"] =~ /\d{2}/
 | 
					 | 
				
			||||||
        raise ArgumentError, "'%s' is not a valid network prefix length" % value["net_length"]
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  newparam(:router) do
 | 
					 | 
				
			||||||
    desc "The MidoNet's internal Provider router that acts as the gateway router of the cloud"
 | 
					 | 
				
			||||||
    defaultto 'MidoNet Provider Router'
 | 
					 | 
				
			||||||
    validate do |value|
 | 
					 | 
				
			||||||
      unless value =~ /\w+$/
 | 
					 | 
				
			||||||
        raise ArgumentError, "'%s' is not a valid router name" % value
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  newparam(:advertise_net) do
 | 
					 | 
				
			||||||
    desc 'Floating IP network to be avertised to the BGP peers'
 | 
					 | 
				
			||||||
    defaultto []
 | 
					 | 
				
			||||||
    validate do |value|
 | 
					 | 
				
			||||||
      if value.class == Hash
 | 
					 | 
				
			||||||
        value = [value]
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
      value.each do |an|
 | 
					 | 
				
			||||||
        unless an["net_prefix"] =~ /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/
 | 
					 | 
				
			||||||
          raise ArgumentError, "'%s' is not a valid IPv4 network address" % an["net_prefix"]
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
        unless an["net_length"] =~ /\d{2}/
 | 
					 | 
				
			||||||
          raise ArgumentError, "'%s' is not a valid network prefix length" % an["net_length"]
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										150
									
								
								lib/puppet/type/midonet_gateway_bgp.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								lib/puppet/type/midonet_gateway_bgp.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,150 @@
 | 
				
			|||||||
 | 
					require 'uri'
 | 
				
			||||||
 | 
					require 'facter'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Puppet::Type.newtype(:midonet_gateway_bgp) do
 | 
				
			||||||
 | 
					  @doc = %q{This type is used to configure a gateway node, considering the
 | 
				
			||||||
 | 
					  uplink is of type BGP. What it does:
 | 
				
			||||||
 | 
					    1) Assign an AS number to the edge router
 | 
				
			||||||
 | 
					    2) Assign BGP peers
 | 
				
			||||||
 | 
					    3) Advertise BGP networks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Usage:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    midonet_gateway_bgp { 'edge_router':
 | 
				
			||||||
 | 
					      bgp_local_as_number     => '65432',
 | 
				
			||||||
 | 
					      bgp_advertised_networks => [
 | 
				
			||||||
 | 
					        '200.0.0.0/24',
 | 
				
			||||||
 | 
					        '12.0.140.0/16',
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      bgp_neighbors           => [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          'ip_address' => '200.0.1.1',
 | 
				
			||||||
 | 
					          'remote_asn' => '34512'
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          'ip_address' => '12.0.140.1',
 | 
				
			||||||
 | 
					          'remote_asn' => '24125'
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      midonet_api_url         => 'http://controller:8181',
 | 
				
			||||||
 | 
					      username                => 'admin',
 | 
				
			||||||
 | 
					      password                => 'admin',
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ensurable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  newparam(:bgp_local_as_number) do
 | 
				
			||||||
 | 
					    desc "AS number of the local BGP autonomous system.  If you have an RIR
 | 
				
			||||||
 | 
					      registered AS number, use it.  If you don't have an RIR registered AS
 | 
				
			||||||
 | 
					      number, use any of the RFC 1930's reserved AS number.  It should be an
 | 
				
			||||||
 | 
					      integer.  Only applicable when uplink_type=='bgp'."
 | 
				
			||||||
 | 
					    validate do |value|
 | 
				
			||||||
 | 
					      unless value =~ /^\d+$/
 | 
				
			||||||
 | 
					        raise ArgumentError, "'%s' is not a valid AS number" % value
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  newparam(:bgp_advertised_networks) do
 | 
				
			||||||
 | 
					    desc "Networks advertised to the remote BGP autonomous system.  This usually
 | 
				
			||||||
 | 
					      should be the same as floating IP networks defined in neutron.  It should
 | 
				
			||||||
 | 
					      be an array of strings, each of which should be a network address
 | 
				
			||||||
 | 
					      in either \"IP/Prefix_Length\" notation (\"192.0.2.0/24\") or
 | 
				
			||||||
 | 
					      \"IP/Subnet_Mask\" nonation(\"192.0.2.0/255.255.255.0\").  Only applicable
 | 
				
			||||||
 | 
					      when uplink_type=='bgp'.  A more elaborate example will be:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [ '192.0.2.128/25', '198.51.100.128/25', '203.0.113.128/25' ]"
 | 
				
			||||||
 | 
					    validate do |value|
 | 
				
			||||||
 | 
					      unless value.class == Array && value.length > 0
 | 
				
			||||||
 | 
					        raise ArgumentError, "#{value} is not an Array"
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					        value.each do |e|
 | 
				
			||||||
 | 
					          unless e.class == String && e =~ /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\/\d+$/
 | 
				
			||||||
 | 
					            raise ArgumentError, "#{e} is not a valid IP address"
 | 
				
			||||||
 | 
					          end
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  newparam(:bgp_neighbors) do
 | 
				
			||||||
 | 
					    desc " An array containing hashes that describe a remote BGP peer. These
 | 
				
			||||||
 | 
					    hashes must have two parameters:
 | 
				
			||||||
 | 
					     - 'ip_address': IP address of the peer
 | 
				
			||||||
 | 
					     - 'remote_asn': Peer's AS number
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    A real life example will look like:
 | 
				
			||||||
 | 
					    [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        'ip_address' => '203.0.113.1',
 | 
				
			||||||
 | 
					        'remote_asn' => '64513'
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        'ip_address' => '198.51.100.1',
 | 
				
			||||||
 | 
					        'remote_asn' => '64514'
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					    "
 | 
				
			||||||
 | 
					    validate do |value|
 | 
				
			||||||
 | 
					      unless value.class == Array && value.length > 0
 | 
				
			||||||
 | 
					        raise ArgumentError, "'%s' is not an array" % value
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					        value.each do |e|
 | 
				
			||||||
 | 
					          unless e.class == Hash && e.key?("ip_address") && e.key?("remote_asn")
 | 
				
			||||||
 | 
					            raise ArgumentError, "'%s' doesn't contain parameters 'ip_address' and/or 'remote_asn'" % value
 | 
				
			||||||
 | 
					          else
 | 
				
			||||||
 | 
					            unless e["ip_address"] =~ /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/
 | 
				
			||||||
 | 
					              raise ArgumentError, "#{e['ip_address']} is not a valid IP address"
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					            unless e["remote_asn"] =~ /^\d+$/
 | 
				
			||||||
 | 
					              raise ArgumentError, "#{e['remote_asn']} is not a valid AS number"
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					          end
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  autorequire(:package) do ['midolman'] end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  newparam(:midonet_api_url) do
 | 
				
			||||||
 | 
					    desc 'MidoNet API endpoint to connect to'
 | 
				
			||||||
 | 
					    validate do |value|
 | 
				
			||||||
 | 
					      unless value =~ /\A#{URI::regexp(['http', 'https'])}\z/
 | 
				
			||||||
 | 
					        raise ArgumentError, "'%s' is not a valid URI" % value
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  newparam(:username) do
 | 
				
			||||||
 | 
					    desc 'Username of the admin user in keystone'
 | 
				
			||||||
 | 
					    defaultto 'admin'
 | 
				
			||||||
 | 
					    validate do |value|
 | 
				
			||||||
 | 
					      unless value =~ /\w+$/
 | 
				
			||||||
 | 
					        raise ArgumentError, "'%s' is not a valid username" % value
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  newparam(:password) do
 | 
				
			||||||
 | 
					    desc 'Password of the admin user in keystone'
 | 
				
			||||||
 | 
					    defaultto 'admin'
 | 
				
			||||||
 | 
					    validate do |value|
 | 
				
			||||||
 | 
					      unless value =~ /\w+$/
 | 
				
			||||||
 | 
					        raise ArgumentError, "'%s' is not a valid password" % value
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  newparam(:router, :namevar => true) do
 | 
				
			||||||
 | 
					    desc "The MidoNet's internal Provider router that acts as the gateway router of the cloud"
 | 
				
			||||||
 | 
					    defaultto 'MidoNet Provider Router'
 | 
				
			||||||
 | 
					    validate do |value|
 | 
				
			||||||
 | 
					      unless value =~ /\w+$/
 | 
				
			||||||
 | 
					        raise ArgumentError, "'%s' is not a valid router name" % value
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
							
								
								
									
										127
									
								
								manifests/gateway/static.pp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								manifests/gateway/static.pp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,127 @@
 | 
				
			|||||||
 | 
					# == Class: midonet::gateway::static
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Set up a fake uplink with static routing on a gateway node
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# === Parameters
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# [*network_id*]
 | 
				
			||||||
 | 
					#   (Mandatory) Name of the bridge that will be created through midonet-cli
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# [*cidr*]
 | 
				
			||||||
 | 
					#   (Mandatory) Network that will be assigned to the fake uplink
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# [*gateway_ip*]
 | 
				
			||||||
 | 
					#   (Mandatory) Gateway IP through which the packets will go
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# [*service_host*]
 | 
				
			||||||
 | 
					#   (Mandatory) Host where the Midonet API runs
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# [*service_dir*]
 | 
				
			||||||
 | 
					#   (Mandatory) Folder on which to place the pidfile and some other temporary
 | 
				
			||||||
 | 
					#   files for the well functioning of this script (ex: /tmp/status)
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# [*zookeeper_hosts*]
 | 
				
			||||||
 | 
					#   (Mandatory) Comma-separated list of zookeeper hosts. These are a hash consisting of two
 | 
				
			||||||
 | 
					#   fields, 'ip' and 'port'. Example: [ { 'ip' => '12.153.140.2', 'port' => '2181'}]
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# [*api_port*]
 | 
				
			||||||
 | 
					#   (Mandatory) Port that the Midonet API binds
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# [*scripts_dir*]
 | 
				
			||||||
 | 
					#   (Optional) Path where to place the necessary scripts
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# [*ensure_scripts*]
 | 
				
			||||||
 | 
					#   (Optional) Status of the scripts
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# [*mido_db_user*]
 | 
				
			||||||
 | 
					#   (Optional) Username to authenticate against the DB
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# [*mido_db_password*]
 | 
				
			||||||
 | 
					#   (Optional) Password to authenticate against the DB
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# === Examples
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The easiest way to run the class is:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#      class { 'midonet::gateway::static':
 | 
				
			||||||
 | 
					#        network_id => 'example_netid',
 | 
				
			||||||
 | 
					#        cidr => '200.0.0.1/24',
 | 
				
			||||||
 | 
					#        gateway_ip => '200.0.0.1',
 | 
				
			||||||
 | 
					#        service_host => '127.0.0.1',
 | 
				
			||||||
 | 
					#        service_dir => '/tmp/status',
 | 
				
			||||||
 | 
					#        zookeeper_hosts => [
 | 
				
			||||||
 | 
					#          {
 | 
				
			||||||
 | 
					#            'ip'=>'127.0.0.1',
 | 
				
			||||||
 | 
					#            'port'=>'2181'
 | 
				
			||||||
 | 
					#          }
 | 
				
			||||||
 | 
					#        ],
 | 
				
			||||||
 | 
					#        api_port => '8181'
 | 
				
			||||||
 | 
					#      }
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# === Authors
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Midonet (http://midonet.org)
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# === Copyright
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c) 2016 Midokura SARL, 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.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class midonet::gateway::static (
 | 
				
			||||||
 | 
					  $network_id,
 | 
				
			||||||
 | 
					  $cidr,
 | 
				
			||||||
 | 
					  $gateway_ip,
 | 
				
			||||||
 | 
					  $service_host,
 | 
				
			||||||
 | 
					  $service_dir,
 | 
				
			||||||
 | 
					  $zookeeper_hosts,
 | 
				
			||||||
 | 
					  $api_port,
 | 
				
			||||||
 | 
					  $scripts_dir       = '/tmp',
 | 
				
			||||||
 | 
					  $uplink_script     = 'create_fake_uplink_l2.sh',
 | 
				
			||||||
 | 
					  $midorc_script     = 'midorc',
 | 
				
			||||||
 | 
					  $functions_script  = 'functions',
 | 
				
			||||||
 | 
					  $ensure_scripts    = 'present',
 | 
				
			||||||
 | 
					  $mido_db_user      = 'admin',
 | 
				
			||||||
 | 
					  $mido_db_password  = 'admin',
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Install screen, as it's needed by the script
 | 
				
			||||||
 | 
					  package { 'screen': ensure => installed }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Place script and helper files before executing it
 | 
				
			||||||
 | 
					  file { 'fake_uplink_script':
 | 
				
			||||||
 | 
					    ensure  => $ensure_scripts,
 | 
				
			||||||
 | 
					    path    => "${scripts_dir}/create_fake_uplink_l2.sh",
 | 
				
			||||||
 | 
					    content => template('midonet/gateway/create_fake_uplink_l2.sh.erb'),
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  file { 'midorc':
 | 
				
			||||||
 | 
					    ensure  => $ensure_scripts,
 | 
				
			||||||
 | 
					    path    => "${scripts_dir}/midorc",
 | 
				
			||||||
 | 
					    content => template('midonet/gateway/midorc.erb'),
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  file { 'functions':
 | 
				
			||||||
 | 
					    ensure  => $ensure_scripts,
 | 
				
			||||||
 | 
					    path    => "${scripts_dir}/functions",
 | 
				
			||||||
 | 
					    source  => 'puppet:///modules/midonet/gateway/functions',
 | 
				
			||||||
 | 
					    require => Package['screen'],
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Finally, execute the script
 | 
				
			||||||
 | 
					  exec { "/bin/bash ${scripts_dir}/create_fake_uplink_l2.sh":
 | 
				
			||||||
 | 
					    require => [
 | 
				
			||||||
 | 
					      File['fake_uplink_script', 'midorc', 'functions'],
 | 
				
			||||||
 | 
					      Package['python-midonetclient'],
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,24 +0,0 @@
 | 
				
			|||||||
require 'spec_helper'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
describe 'midonet::cluster' do
 | 
					 | 
				
			||||||
  context 'with parameters' do
 | 
					 | 
				
			||||||
    let :facts do
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        :osfamily       => 'Debian',
 | 
					 | 
				
			||||||
        :lsbdistid      => 'Ubuntu',
 | 
					 | 
				
			||||||
        :lsbdistrelease => '16.04',
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    let :params do
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        :zookeeper_hosts       => ['{ "ip" => "127.0.0.1", "port" => "2181" }'],
 | 
					 | 
				
			||||||
        :cassandra_servers      => [ '127.0.0.1' ],
 | 
					 | 
				
			||||||
        :cassandra_rep_factor => '3',
 | 
					 | 
				
			||||||
        :keystone_admin_token => 'ADMIN_TOKEN',
 | 
					 | 
				
			||||||
        :keystone_host => '127.0.0.1',
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    it { is_expected.to contain_class('midonet::cluster::install') }
 | 
					 | 
				
			||||||
    it { is_expected.to contain_class('midonet::cluster::run') }
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
							
								
								
									
										29
									
								
								spec/classes/midonet_gateway_static_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								spec/classes/midonet_gateway_static_spec.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					require 'spec_helper'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe 'midonet::gateway::static' do
 | 
				
			||||||
 | 
					  context 'with parameters' do
 | 
				
			||||||
 | 
					    let :facts do
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        :osfamily       => 'Debian',
 | 
				
			||||||
 | 
					        :lsbdistid      => 'Ubuntu',
 | 
				
			||||||
 | 
					        :lsbdistrelease => '16.04',
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    let :params do
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        :network_id => 'example_netid',
 | 
				
			||||||
 | 
					        :cidr => '200.0.0.1/24',
 | 
				
			||||||
 | 
					        :gateway_ip => '200.0.0.1',
 | 
				
			||||||
 | 
					        :service_host => '127.0.0.1',
 | 
				
			||||||
 | 
					        :service_dir => '/tmp/status',
 | 
				
			||||||
 | 
					        :zookeeper_hosts => [ { 'ip' => '127.0.0.1', 'port' => '2181' } ],
 | 
				
			||||||
 | 
					        :api_port => '8181'
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    it { is_expected.to contain_package('screen').with_ensure('installed') }
 | 
				
			||||||
 | 
					    it { is_expected.to contain_file('fake_uplink_script').with_ensure('present') }
 | 
				
			||||||
 | 
					    it { is_expected.to contain_file('midorc').with_ensure('present') }
 | 
				
			||||||
 | 
					    it { is_expected.to contain_file('functions').with_ensure('present') }
 | 
				
			||||||
 | 
					    it { is_expected.to contain_exec('/bin/bash /tmp/create_fake_uplink_l2.sh') }
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@@ -1,158 +1,108 @@
 | 
				
			|||||||
require 'spec_helper'
 | 
					require 'spec_helper'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe Puppet::Type.type(:midonet_gateway).provider(:midonet_api_caller) do
 | 
					describe Puppet::Type.type(:midonet_gateway_bgp).provider(:midonet_api_caller) do
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let(:provider) { described_class.new(resource) }
 | 
					  let(:provider) { described_class.new(resource) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let(:resource) { Puppet::Type.type(:midonet_gateway).new(
 | 
					  let(:resource) do
 | 
				
			||||||
    {
 | 
					    Puppet::Type::type(:midonet_gateway_bgp).new(
 | 
				
			||||||
      :ensure              => :present,
 | 
					    :router                  => 'edge_router',
 | 
				
			||||||
      :hostname            => 'compute.midonet',
 | 
					    :midonet_api_url         => 'http://controller:8080/midonet-api',
 | 
				
			||||||
      :midonet_api_url     => 'http://controller:8080',
 | 
					    :username                => 'admin',
 | 
				
			||||||
      :username            => 'admin',
 | 
					    :password                => 'admin',
 | 
				
			||||||
      :password            => 'admin',
 | 
					    :bgp_local_as_number     => '64512',
 | 
				
			||||||
      :interface           => 'eth0',
 | 
					    :bgp_neighbors           => [
 | 
				
			||||||
      :local_as            => '64512',
 | 
					      {
 | 
				
			||||||
      :bgp_port            => { 'port_address' => '198.51.100.2', 'net_prefix' => '198.51.100.0', 'net_length' => '30' },
 | 
					        'ip_address' => '200.100.98.7',
 | 
				
			||||||
      :remote_peers        => [ { 'as' => '64513', 'ip' => '198.51.100.1' },
 | 
					        'remote_asn' => '45237',
 | 
				
			||||||
                                { 'as' => '64513', 'ip' => '203.0.113.1' } ],
 | 
					      },
 | 
				
			||||||
      :advertise_net       => [ { 'net_prefix' => '192.0.2.0', 'net_length' => '24' } ]
 | 
					      {
 | 
				
			||||||
    }
 | 
					        'ip_address' => '182.24.63.2',
 | 
				
			||||||
  )}
 | 
					        'remote_asn' => '45235',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    :bgp_advertised_networks => [ '200.0.0.0/24', '200.0.20.0/24' ] )
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  describe 'BGP configuration happy path' do
 | 
					  describe 'BGP configuration happy path' do
 | 
				
			||||||
    # - Create virtual ports for each remote BGP peer
 | 
					 | 
				
			||||||
    # - Configure BGP on the virtual ports or remove config if needed
 | 
					 | 
				
			||||||
    # - Advertise routes
 | 
					 | 
				
			||||||
    # - Bind virtual ports to physical network interfaces
 | 
					 | 
				
			||||||
    # - Configure stateful port group and delete it if needed
 | 
					 | 
				
			||||||
    # - Add ports to the port group and remove them if needed
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # 1) Assign AS number to router
 | 
				
			||||||
 | 
					    # 2) Assign BGP neighbors to routers
 | 
				
			||||||
 | 
					    # 3) Advertise floating IP network
 | 
				
			||||||
 | 
					    # 4) Delete BGP neighbors
 | 
				
			||||||
 | 
					    # 5) De-advertise networks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Other parameters are returned by default, but only this one is needed for
 | 
				
			||||||
 | 
					    # testing purposes
 | 
				
			||||||
 | 
					    # More info: https://docs.midonet.org/docs/latest/rest-api/content/router.html
 | 
				
			||||||
    let(:routers) {
 | 
					    let(:routers) {
 | 
				
			||||||
      [
 | 
					      [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
         "id"   => "e6a53892-03bf-4f16-8212-e4d76ad204e3",
 | 
					         "id"   => "e6a53892-03bf-4f16-8212-e4d76ad204e3",
 | 
				
			||||||
         "name" => "MidoNet Provider Router"
 | 
					         "name" => "edge_router"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      ]
 | 
					      ]
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    # Other parameters are returned by default, but only this one is needed for
 | 
				
			||||||
    let(:ports) {
 | 
					    # testing purposes
 | 
				
			||||||
 | 
					    # More info: https://docs.midonet.org/docs/latest/rest-api/content/bgp-peer.html
 | 
				
			||||||
 | 
					    let(:bgp_peers) {
 | 
				
			||||||
      [
 | 
					      [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "hostId"        => "b3f2f63e-02a6-459a-af0f-44eeac441a09",
 | 
					          "id" => "4a5e4356-3417-4c60-9cf8-7516aedb7067",
 | 
				
			||||||
          "interfaceName" => "eth0",
 | 
					 | 
				
			||||||
          "id"            => "20b169b1-ec0a-4639-8479-44b63e016935"
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      ]
 | 
					      ]
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    # Other parameters are returned by default, but only this one is needed for
 | 
				
			||||||
    let(:bgps) {
 | 
					    # testing purposes
 | 
				
			||||||
 | 
					    # More info: https://docs.midonet.org/docs/latest/rest-api/content/bgp-network.html
 | 
				
			||||||
 | 
					    let(:bgp_networks) {
 | 
				
			||||||
      [
 | 
					      [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "id"          => "4a5e4356-3417-4c60-9cf8-7516aedb7067",
 | 
					          "id" => "4a5e4356-3417-4c60-9cf8-7516abcd1234",
 | 
				
			||||||
          "localAS"     => "64512",
 | 
					 | 
				
			||||||
          "peerAS"      => "64513",
 | 
					 | 
				
			||||||
          "peerAddr"    => "198.51.100.1",
 | 
					 | 
				
			||||||
          "portId"      => "f9e61b88-0a26-4d56-8f47-eb5da37225e0"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      ]
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let(:port_groups) {
 | 
					 | 
				
			||||||
      [
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          "id"       => "711401b7-bf6f-4afd-8ab2-94b4342a0310",
 | 
					 | 
				
			||||||
          "name"     => "uplink-spg",
 | 
					 | 
				
			||||||
          "stateful" => "true"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      ]
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let(:hosts) {
 | 
					 | 
				
			||||||
      [
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          "id"   => "b3f2f63e-02a6-459a-af0f-44eeac441a09",
 | 
					 | 
				
			||||||
          "name" => "compute.midonet"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      ]
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let(:tenants) {
 | 
					 | 
				
			||||||
      [
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          "id"   => "4486908d-8e15-4f01-b3b4-86f9def0fa04",
 | 
					 | 
				
			||||||
          "name" => "4486908d-8e15-4f01-b3b4-86f9def0fa04"
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      ]
 | 
					      ]
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    before :each do
 | 
					    before :each do
 | 
				
			||||||
      allow(provider).to receive(:call_create_uplink_port).and_return(ports)
 | 
					 | 
				
			||||||
      allow(provider).to receive(:call_get_provider_router).and_return(routers)
 | 
					 | 
				
			||||||
      allow(provider).to receive(:call_get_host_id).and_return(hosts[0]['id'])
 | 
					 | 
				
			||||||
      allow(provider).to receive(:call_get_host).and_return(hosts)
 | 
					 | 
				
			||||||
      allow(provider).to receive(:call_add_bgp_to_port)
 | 
					 | 
				
			||||||
      allow(provider).to receive(:call_get_bgp_connections).and_return(bgps)
 | 
					 | 
				
			||||||
      allow(provider).to receive(:call_advertise_route_to_bgp)
 | 
					 | 
				
			||||||
      allow(provider).to receive(:call_bind_port_to_interface)
 | 
					 | 
				
			||||||
      allow(provider).to receive(:call_get_stateful_port_group).and_return(port_groups)
 | 
					 | 
				
			||||||
      allow(provider).to receive(:call_add_ports_to_port_group)
 | 
					 | 
				
			||||||
      allow(provider).to receive(:call_delete_uplink_port).and_return(ports)
 | 
					 | 
				
			||||||
      allow(provider).to receive(:call_unbind_port_from_interface)
 | 
					 | 
				
			||||||
      allow(provider).to receive(:call_remove_ports_from_port_group)
 | 
					 | 
				
			||||||
      allow(provider).to receive(:call_get_uplink_port).and_return(ports)
 | 
					 | 
				
			||||||
      allow(provider).to receive(:call_add_route_for_uplink_port)
 | 
					 | 
				
			||||||
      allow(provider).to receive(:call_get_token).and_return('thisisafaketoken')
 | 
					      allow(provider).to receive(:call_get_token).and_return('thisisafaketoken')
 | 
				
			||||||
      allow(provider).to receive(:call_get_tenant).and_return(tenants)
 | 
					      allow(provider).to receive(:call_get_provider_router).and_return(routers)
 | 
				
			||||||
 | 
					      allow(provider).to receive(:call_assign_asn)
 | 
				
			||||||
 | 
					      allow(provider).to receive(:call_add_bgp_peer)
 | 
				
			||||||
 | 
					      allow(provider).to receive(:call_advertise_bgp_network)
 | 
				
			||||||
 | 
					      allow(provider).to receive(:call_get_bgp_peers).and_return(bgp_peers)
 | 
				
			||||||
 | 
					      allow(provider).to receive(:call_delete_bgp_peer)
 | 
				
			||||||
 | 
					      allow(provider).to receive(:call_get_bgp_networks).and_return(bgp_networks.map { |e| e['id'] })
 | 
				
			||||||
 | 
					      allow(provider).to receive(:call_delete_bgp_network)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    it 'creates virtual ports for each remote BGP peer, advertises routes,
 | 
					    it 'follows happy path (BGP)' do
 | 
				
			||||||
      binds virtual ports, configures stateful port group and adds ports to it' do
 | 
					 | 
				
			||||||
      # Expectations over the 'create' call
 | 
					 | 
				
			||||||
      expect(provider).to receive(:call_get_provider_router)
 | 
					      expect(provider).to receive(:call_get_provider_router)
 | 
				
			||||||
      expect(provider).to receive(:call_create_uplink_port).with(routers[0]['id'], {'portAddress'    => resource[:bgp_port]['port_address'],
 | 
					      expect(provider).to receive(:call_assign_asn)
 | 
				
			||||||
                                                                                    'networkAddress' => resource[:bgp_port]['net_prefix'],
 | 
					      expect(provider).to receive(:call_add_bgp_peer).with(routers[0]['id'], '200.100.98.7', '45237')
 | 
				
			||||||
                                                                                    'networkLength'  => resource[:bgp_port]['net_length'].to_i,
 | 
					      expect(provider).to receive(:call_add_bgp_peer).with(routers[0]['id'], '182.24.63.2', '45235')
 | 
				
			||||||
                                                                                    'type' => 'Router'})
 | 
					      expect(provider).to receive(:call_advertise_bgp_network).with(routers[0]['id'], '200.0.0.0/24')
 | 
				
			||||||
      expect(provider).to receive(:call_get_bgp_connections).with(ports[0]['id'])
 | 
					      expect(provider).to receive(:call_advertise_bgp_network).with(routers[0]['id'], '200.0.20.0/24')
 | 
				
			||||||
      expect(provider).to receive(:call_add_bgp_to_port).with(ports[0]['id'], {'localAS'  => resource[:local_as],
 | 
					      expect(provider).to receive(:call_get_bgp_peers).with(routers[0]['id'])
 | 
				
			||||||
                                                                               'peerAS'   => resource[:remote_peers][0]['as'],
 | 
					      expect(provider).to receive(:call_delete_bgp_peer).with(bgp_peers[0]['id'])
 | 
				
			||||||
                                                                               'peerAddr' => resource[:remote_peers][0]['ip']}).once
 | 
					      expect(provider).to receive(:call_get_bgp_networks).with(routers[0]['id'])
 | 
				
			||||||
      expect(provider).to receive(:call_add_bgp_to_port).with(ports[0]['id'], {'localAS'  => resource[:local_as],
 | 
					      expect(provider).to receive(:call_delete_bgp_network).with(bgp_networks[0]['id'])
 | 
				
			||||||
                                                                               'peerAS'   => resource[:remote_peers][1]['as'],
 | 
					 | 
				
			||||||
                                                                               'peerAddr' => resource[:remote_peers][1]['ip']}).once
 | 
					 | 
				
			||||||
      expect(provider).to receive(:call_add_route_for_uplink_port).with(routers[0]['id'], {'type'             => 'Normal',
 | 
					 | 
				
			||||||
                                                                                           'srcNetworkAddr'   => '0.0.0.0',
 | 
					 | 
				
			||||||
                                                                                           'srcNetworkLength' => 0,
 | 
					 | 
				
			||||||
                                                                                           'dstNetworkAddr'   => resource[:bgp_port]['net_prefix'],
 | 
					 | 
				
			||||||
                                                                                           'dstNetworkLength' => resource[:bgp_port]['net_length'].to_i,
 | 
					 | 
				
			||||||
                                                                                           'weight'           => 100,
 | 
					 | 
				
			||||||
                                                                                           'nextHopPort'      => ports[0]['id']})
 | 
					 | 
				
			||||||
      expect(provider).to receive(:call_advertise_route_to_bgp).with(bgps[0]['id'], {'nwPrefix'     => resource[:advertise_net][0]['net_prefix'],
 | 
					 | 
				
			||||||
                                                                                     'prefixLength' => resource[:advertise_net][0]['net_length']}).once
 | 
					 | 
				
			||||||
      expect(provider).to receive(:call_bind_port_to_interface).with(hosts[0]['id'], {'interfaceName' => resource[:interface],
 | 
					 | 
				
			||||||
                                                                                      'portId'        => '20b169b1-ec0a-4639-8479-44b63e016935'})
 | 
					 | 
				
			||||||
      expect(provider).not_to receive(:call_create_stateful_port_group)
 | 
					 | 
				
			||||||
      expect(provider).to receive(:call_get_stateful_port_group)
 | 
					 | 
				
			||||||
      expect(provider).to receive(:call_add_ports_to_port_group).with(port_groups[0]['id'], {'portId' => '20b169b1-ec0a-4639-8479-44b63e016935'})
 | 
					 | 
				
			||||||
      provider.create
 | 
					      provider.create
 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    it 'deletes uplink port, port_group, and unconfigures BGP' do
 | 
					 | 
				
			||||||
      # Expectations over the 'destroy' call
 | 
					 | 
				
			||||||
      expect(provider).to receive(:call_get_provider_router)
 | 
					 | 
				
			||||||
      expect(provider).to receive(:call_get_uplink_port)
 | 
					 | 
				
			||||||
      expect(provider).to receive(:call_delete_uplink_port).with(ports[0]['id'])
 | 
					 | 
				
			||||||
      provider.destroy
 | 
					      provider.destroy
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    it 'exists with default method returns' do
 | 
					    it 'deletes BGP peers, and stops advertising the floating IP network' do
 | 
				
			||||||
      # Expectations over the 'exists' call
 | 
					      expect(provider).to receive(:call_get_provider_router)
 | 
				
			||||||
      expect(provider).to receive(:call_get_provider_router).and_return(routers)
 | 
					      expect(provider).to receive(:call_get_bgp_peers).with(routers[0]['id'])
 | 
				
			||||||
      expect(provider).to receive(:call_get_host).and_return(hosts)
 | 
					      expect(provider).to receive(:call_delete_bgp_peer).with(bgp_peers[0]['id'])
 | 
				
			||||||
      expect(provider).to receive(:call_get_uplink_port).with(routers[0]['id'], resource[:bgp_port]['port_address']).and_return(ports)
 | 
					      expect(provider).to receive(:call_get_bgp_networks).with(routers[0]['id'])
 | 
				
			||||||
      expect(provider.exists?).to eq true
 | 
					      expect(provider).to receive(:call_delete_bgp_network).with(bgp_networks[0]['id'])
 | 
				
			||||||
 | 
					      provider.destroy
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it 'checks if a given provider router exists' do
 | 
				
			||||||
 | 
					      expect(provider).to receive(:call_get_provider_router)
 | 
				
			||||||
 | 
					      provider.exists?
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,108 @@
 | 
				
			|||||||
 | 
					require 'spec_helper'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe Puppet::Type.type(:midonet_gateway_bgp).provider(:midonet_api_caller) do
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let(:provider) { described_class.new(resource) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let(:resource) do
 | 
				
			||||||
 | 
					    Puppet::Type::type(:midonet_gateway_bgp).new(
 | 
				
			||||||
 | 
					    :router                  => 'edge_router',
 | 
				
			||||||
 | 
					    :midonet_api_url         => 'http://controller:8080/midonet-api',
 | 
				
			||||||
 | 
					    :username                => 'admin',
 | 
				
			||||||
 | 
					    :password                => 'admin',
 | 
				
			||||||
 | 
					    :bgp_local_as_number     => '64512',
 | 
				
			||||||
 | 
					    :bgp_neighbors           => [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        'ip_address' => '200.100.98.7',
 | 
				
			||||||
 | 
					        'remote_asn' => '45237',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        'ip_address' => '182.24.63.2',
 | 
				
			||||||
 | 
					        'remote_asn' => '45235',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    :bgp_advertised_networks => [ '200.0.0.0/24', '200.0.20.0/24' ] )
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  describe 'BGP configuration happy path' do
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # 1) Assign AS number to router
 | 
				
			||||||
 | 
					    # 2) Assign BGP neighbors to routers
 | 
				
			||||||
 | 
					    # 3) Advertise floating IP network
 | 
				
			||||||
 | 
					    # 4) Delete BGP neighbors
 | 
				
			||||||
 | 
					    # 5) De-advertise networks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Other parameters are returned by default, but only this one is needed for
 | 
				
			||||||
 | 
					    # testing purposes
 | 
				
			||||||
 | 
					    # More info: https://docs.midonet.org/docs/latest/rest-api/content/router.html
 | 
				
			||||||
 | 
					    let(:routers) {
 | 
				
			||||||
 | 
					      [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					         "id"   => "e6a53892-03bf-4f16-8212-e4d76ad204e3",
 | 
				
			||||||
 | 
					         "name" => "edge_router"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      ]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    # Other parameters are returned by default, but only this one is needed for
 | 
				
			||||||
 | 
					    # testing purposes
 | 
				
			||||||
 | 
					    # More info: https://docs.midonet.org/docs/latest/rest-api/content/bgp-peer.html
 | 
				
			||||||
 | 
					    let(:bgp_peers) {
 | 
				
			||||||
 | 
					      [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "id" => "4a5e4356-3417-4c60-9cf8-7516aedb7067",
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      ]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    # Other parameters are returned by default, but only this one is needed for
 | 
				
			||||||
 | 
					    # testing purposes
 | 
				
			||||||
 | 
					    # More info: https://docs.midonet.org/docs/latest/rest-api/content/bgp-network.html
 | 
				
			||||||
 | 
					    let(:bgp_networks) {
 | 
				
			||||||
 | 
					      [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "id" => "4a5e4356-3417-4c60-9cf8-7516abcd1234",
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      ]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    before :each do
 | 
				
			||||||
 | 
					      allow(provider).to receive(:call_get_token).and_return('thisisafaketoken')
 | 
				
			||||||
 | 
					      allow(provider).to receive(:call_get_provider_router).and_return(routers)
 | 
				
			||||||
 | 
					      allow(provider).to receive(:call_assign_asn)
 | 
				
			||||||
 | 
					      allow(provider).to receive(:call_add_bgp_peer)
 | 
				
			||||||
 | 
					      allow(provider).to receive(:call_advertise_bgp_network)
 | 
				
			||||||
 | 
					      allow(provider).to receive(:call_get_bgp_peers).and_return(bgp_peers)
 | 
				
			||||||
 | 
					      allow(provider).to receive(:call_delete_bgp_peer)
 | 
				
			||||||
 | 
					      allow(provider).to receive(:call_get_bgp_networks).and_return(bgp_networks.map { |e| e['id'] })
 | 
				
			||||||
 | 
					      allow(provider).to receive(:call_delete_bgp_network)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it 'follows happy path (BGP)' do
 | 
				
			||||||
 | 
					      expect(provider).to receive(:call_get_provider_router)
 | 
				
			||||||
 | 
					      expect(provider).to receive(:call_assign_asn)
 | 
				
			||||||
 | 
					      expect(provider).to receive(:call_add_bgp_peer).with(routers[0]['id'], '200.100.98.7', '45237')
 | 
				
			||||||
 | 
					      expect(provider).to receive(:call_add_bgp_peer).with(routers[0]['id'], '182.24.63.2', '45235')
 | 
				
			||||||
 | 
					      expect(provider).to receive(:call_advertise_bgp_network).with(routers[0]['id'], '200.0.0.0/24')
 | 
				
			||||||
 | 
					      expect(provider).to receive(:call_advertise_bgp_network).with(routers[0]['id'], '200.0.20.0/24')
 | 
				
			||||||
 | 
					      expect(provider).to receive(:call_get_bgp_peers).with(routers[0]['id'])
 | 
				
			||||||
 | 
					      expect(provider).to receive(:call_delete_bgp_peer).with(bgp_peers[0]['id'])
 | 
				
			||||||
 | 
					      expect(provider).to receive(:call_get_bgp_networks).with(routers[0]['id'])
 | 
				
			||||||
 | 
					      expect(provider).to receive(:call_delete_bgp_network).with(bgp_networks[0]['id'])
 | 
				
			||||||
 | 
					      provider.create
 | 
				
			||||||
 | 
					      provider.destroy
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it 'deletes BGP peers, and stops advertising the floating IP network' do
 | 
				
			||||||
 | 
					      expect(provider).to receive(:call_get_provider_router)
 | 
				
			||||||
 | 
					      expect(provider).to receive(:call_get_bgp_peers).with(routers[0]['id'])
 | 
				
			||||||
 | 
					      expect(provider).to receive(:call_delete_bgp_peer).with(bgp_peers[0]['id'])
 | 
				
			||||||
 | 
					      expect(provider).to receive(:call_get_bgp_networks).with(routers[0]['id'])
 | 
				
			||||||
 | 
					      expect(provider).to receive(:call_delete_bgp_network).with(bgp_networks[0]['id'])
 | 
				
			||||||
 | 
					      provider.destroy
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it 'checks if a given provider router exists' do
 | 
				
			||||||
 | 
					      expect(provider).to receive(:call_get_provider_router)
 | 
				
			||||||
 | 
					      provider.exists?
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
							
								
								
									
										73
									
								
								spec/unit/puppet/type/midonet_gateway_bgp_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								spec/unit/puppet/type/midonet_gateway_bgp_spec.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
				
			|||||||
 | 
					require 'spec_helper'
 | 
				
			||||||
 | 
					require 'puppet'
 | 
				
			||||||
 | 
					require 'puppet/type/midonet_gateway_bgp'
 | 
				
			||||||
 | 
					require 'facter'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe Puppet::Type::type(:midonet_gateway_bgp) do
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  context 'on default values (bgp)' do
 | 
				
			||||||
 | 
					    let(:resource) do
 | 
				
			||||||
 | 
					      Puppet::Type::type(:midonet_gateway_bgp).new(
 | 
				
			||||||
 | 
					      :router                  => 'edge_router',
 | 
				
			||||||
 | 
					      :midonet_api_url         => 'http://controller:8080/midonet-api',
 | 
				
			||||||
 | 
					      :username                => 'admin',
 | 
				
			||||||
 | 
					      :password                => 'admin',
 | 
				
			||||||
 | 
					      :bgp_local_as_number     => '64512',
 | 
				
			||||||
 | 
					      :bgp_neighbors           => [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          'ip_address' => '200.100.98.7',
 | 
				
			||||||
 | 
					          'remote_asn' => '45237',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          'ip_address' => '182.24.63.2',
 | 
				
			||||||
 | 
					          'remote_asn' => '45235',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      :bgp_advertised_networks => [ '200.0.0.0/24', '200.0.20.0/24' ] )
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it 'assign the default values' do
 | 
				
			||||||
 | 
					      expect(resource[:username]).to eq 'admin'
 | 
				
			||||||
 | 
					      expect(resource[:password]).to eq 'admin'
 | 
				
			||||||
 | 
					      expect(resource[:router]).to eq 'edge_router'
 | 
				
			||||||
 | 
					      expect(resource[:bgp_local_as_number]).to eq '64512'
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  context 'on invalid api url' do
 | 
				
			||||||
 | 
					    it do
 | 
				
			||||||
 | 
					      expect {
 | 
				
			||||||
 | 
					        Puppet::Type.type(:midonet_gateway_bgp).new(
 | 
				
			||||||
 | 
					        :router          => 'edge_router',
 | 
				
			||||||
 | 
					        :midonet_api_url => '87.23.43.2:8080/midonet-api',
 | 
				
			||||||
 | 
					        :username        => 'admin',
 | 
				
			||||||
 | 
					        :password        => 'admin')
 | 
				
			||||||
 | 
					      }.to raise_error(Puppet::ResourceError)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  context 'on invalid bgp neighbors' do
 | 
				
			||||||
 | 
					    it do
 | 
				
			||||||
 | 
					      expect {
 | 
				
			||||||
 | 
					        Puppet::Type.type(:midonet_gateway_bgp).new(
 | 
				
			||||||
 | 
					        :router        => 'edge_router',
 | 
				
			||||||
 | 
					        :bgp_neighbors => '["12.13.14.15"]',
 | 
				
			||||||
 | 
					        :username      => 'admin',
 | 
				
			||||||
 | 
					        :password      => 'admin')
 | 
				
			||||||
 | 
					      }.to raise_error(Puppet::ResourceError)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  context 'on advertising invalid networks' do
 | 
				
			||||||
 | 
					    it do
 | 
				
			||||||
 | 
					      expect {
 | 
				
			||||||
 | 
					        Puppet::Type.type(:midonet_gateway_bgp).new(
 | 
				
			||||||
 | 
					        :router                  => 'edge_router',
 | 
				
			||||||
 | 
					        :bgp_advertised_networks => ["12.13.14.15", "11.33.44.55/12"],
 | 
				
			||||||
 | 
					        :username                => 'admin',
 | 
				
			||||||
 | 
					        :password                => 'admin')
 | 
				
			||||||
 | 
					      }.to raise_error(Puppet::ResourceError)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@@ -1,202 +0,0 @@
 | 
				
			|||||||
require 'spec_helper'
 | 
					 | 
				
			||||||
require 'puppet'
 | 
					 | 
				
			||||||
require 'puppet/type/midonet_gateway'
 | 
					 | 
				
			||||||
require 'facter'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
describe Puppet::Type::type(:midonet_gateway) do
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    context 'on default values' do
 | 
					 | 
				
			||||||
        let(:resource) do
 | 
					 | 
				
			||||||
            Puppet::Type::type(:midonet_gateway).new(
 | 
					 | 
				
			||||||
                :hostname        => Facter['hostname'].value,
 | 
					 | 
				
			||||||
                :midonet_api_url => 'http://controller:8080/midonet-api',
 | 
					 | 
				
			||||||
                :username        => 'admin',
 | 
					 | 
				
			||||||
                :password        => 'admin',
 | 
					 | 
				
			||||||
                :interface       => 'eth0',
 | 
					 | 
				
			||||||
                :local_as        => '64512',
 | 
					 | 
				
			||||||
                :bgp_port        => { 'port_address' => '198.51.100.2', 'net_prefix' => '198.51.100.0', 'net_length' => '30'},
 | 
					 | 
				
			||||||
                :remote_peers    => [ { 'as' => '64513', 'ip' => '198.51.100.1' },
 | 
					 | 
				
			||||||
                                      { 'as' => '64513', 'ip' => '203.0.113.1' } ],
 | 
					 | 
				
			||||||
                :advertise_net   => [ { 'net_prefix' => '192.0.2.0', 'net_length' => '24' } ])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        it 'assign the default values' do
 | 
					 | 
				
			||||||
            expect(resource[:username]).to eq 'admin'
 | 
					 | 
				
			||||||
            expect(resource[:password]).to eq 'admin'
 | 
					 | 
				
			||||||
            expect(resource[:tenant_name]).to eq 'admin'
 | 
					 | 
				
			||||||
            expect(resource[:interface]).to eq 'eth0'
 | 
					 | 
				
			||||||
            expect(resource[:router]).to eq 'MidoNet Provider Router'
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    context 'on invalid hostname' do
 | 
					 | 
				
			||||||
        it do
 | 
					 | 
				
			||||||
            expect {
 | 
					 | 
				
			||||||
                Puppet::Type.type(:midonet_gateway).new(
 | 
					 | 
				
			||||||
                    :hostname        => '_invalid_hostname.local',
 | 
					 | 
				
			||||||
                    :midonet_api_url => 'http://87.23.43.2:8080/midonet-api',
 | 
					 | 
				
			||||||
                    :username        => 'admin',
 | 
					 | 
				
			||||||
                    :password        => 'admin')
 | 
					 | 
				
			||||||
                }.to raise_error(Puppet::ResourceError)
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    context 'on invalid api url' do
 | 
					 | 
				
			||||||
        it do
 | 
					 | 
				
			||||||
            expect {
 | 
					 | 
				
			||||||
                Puppet::Type.type(:midonet_gateway).new(
 | 
					 | 
				
			||||||
                    :hostname        => Facter['hostname'].value,
 | 
					 | 
				
			||||||
                    :midonet_api_url => '87.23.43.2:8080/midonet-api',
 | 
					 | 
				
			||||||
                    :username        => 'admin',
 | 
					 | 
				
			||||||
                    :password        => 'admin')
 | 
					 | 
				
			||||||
                }.to raise_error(Puppet::ResourceError)
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    context 'on tenant_name valid value' do
 | 
					 | 
				
			||||||
        let(:resource) do
 | 
					 | 
				
			||||||
            Puppet::Type.type(:midonet_gateway).new(
 | 
					 | 
				
			||||||
                :hostname        => Facter['hostname'].value,
 | 
					 | 
				
			||||||
                :midonet_api_url => 'http://87.23.43.2:8080/midonet-api',
 | 
					 | 
				
			||||||
                :username        => 'admin',
 | 
					 | 
				
			||||||
                :password        => 'admin',
 | 
					 | 
				
			||||||
                :tenant_name     => 'midokura')
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        it 'assign to it' do
 | 
					 | 
				
			||||||
            expect(resource[:tenant_name]).to eq 'midokura'
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    context 'on valid interface name without vlan tag' do
 | 
					 | 
				
			||||||
        let(:resource) do
 | 
					 | 
				
			||||||
            Puppet::Type.type(:midonet_gateway).new(
 | 
					 | 
				
			||||||
                :hostname        => Facter['hostname'].value,
 | 
					 | 
				
			||||||
                :midonet_api_url => 'http://87.23.43.2:8080/midonet-api',
 | 
					 | 
				
			||||||
                :username        => 'admin',
 | 
					 | 
				
			||||||
                :password        => 'admin',
 | 
					 | 
				
			||||||
                :interface       => 'eth0')
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        it 'assign to it' do
 | 
					 | 
				
			||||||
            expect(resource[:interface]).to eq 'eth0'
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    context 'on valid interface name with vlan tag' do
 | 
					 | 
				
			||||||
        let(:resource) do
 | 
					 | 
				
			||||||
            Puppet::Type.type(:midonet_gateway).new(
 | 
					 | 
				
			||||||
                :hostname        => Facter['hostname'].value,
 | 
					 | 
				
			||||||
                :midonet_api_url => 'http://87.23.43.2:8080/midonet-api',
 | 
					 | 
				
			||||||
                :username        => 'admin',
 | 
					 | 
				
			||||||
                :password        => 'admin',
 | 
					 | 
				
			||||||
                :interface       => 'eth0.9')
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        it 'assign to it' do
 | 
					 | 
				
			||||||
            expect(resource[:interface]).to eq 'eth0.9'
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    context 'on invalid interface name' do
 | 
					 | 
				
			||||||
        it  do
 | 
					 | 
				
			||||||
          expect {
 | 
					 | 
				
			||||||
            Puppet::Type.type(:midonet_gateway).new(
 | 
					 | 
				
			||||||
                :hostname        => Facter['hostname'].value,
 | 
					 | 
				
			||||||
                :midonet_api_url => 'http://87.23.43.2:8080/midonet-api',
 | 
					 | 
				
			||||||
                :username        => 'admin',
 | 
					 | 
				
			||||||
                :password        => 'admin',
 | 
					 | 
				
			||||||
                :interface       => 'eth0.9a')
 | 
					 | 
				
			||||||
          }.to raise_error(Puppet::ResourceError)
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    context 'on valid local AS name' do
 | 
					 | 
				
			||||||
        let(:resource) do
 | 
					 | 
				
			||||||
            Puppet::Type.type(:midonet_gateway).new(
 | 
					 | 
				
			||||||
                :hostname        => Facter['hostname'].value,
 | 
					 | 
				
			||||||
                :midonet_api_url => 'http://87.23.43.2:8080/midonet-api',
 | 
					 | 
				
			||||||
                :username        => 'admin',
 | 
					 | 
				
			||||||
                :password        => 'admin',
 | 
					 | 
				
			||||||
                :local_as        => '64512')
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        it 'assign to it' do
 | 
					 | 
				
			||||||
            expect(resource[:local_as]).to eq '64512'
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    context 'on invalid local AS name' do
 | 
					 | 
				
			||||||
        it do
 | 
					 | 
				
			||||||
            expect {
 | 
					 | 
				
			||||||
                Puppet::Type.type(:midonet_gateway).new(
 | 
					 | 
				
			||||||
                    :hostname        => Facter['hostname'].value,
 | 
					 | 
				
			||||||
                    :midonet_api_url => 'http://87.23.43.2:8080/midonet-api',
 | 
					 | 
				
			||||||
                    :username        => 'admin',
 | 
					 | 
				
			||||||
                    :password        => 'admin',
 | 
					 | 
				
			||||||
                    :local_as        => 'fake')
 | 
					 | 
				
			||||||
                }.to raise_error(Puppet::ResourceError)
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    context 'on invalid BGP port' do
 | 
					 | 
				
			||||||
        it do
 | 
					 | 
				
			||||||
            expect {
 | 
					 | 
				
			||||||
                Puppet::Type.type(:midonet_gateway).new(
 | 
					 | 
				
			||||||
                    :hostname        => Facter['hostname'].value,
 | 
					 | 
				
			||||||
                    :midonet_api_url => 'http://87.23.43.2:8080/midonet-api',
 | 
					 | 
				
			||||||
                    :username        => 'admin',
 | 
					 | 
				
			||||||
                    :password        => 'admin',
 | 
					 | 
				
			||||||
                    :bgp_port        => { 'port_address' => '_198.51.100.2',
 | 
					 | 
				
			||||||
                                          'net_prefix'  => '198.51.100.0',
 | 
					 | 
				
			||||||
                                          'net_length'   => '30' })
 | 
					 | 
				
			||||||
                }.to raise_error(Puppet::ResourceError)
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    context 'on invalid remote BGP peers AS name and IP' do
 | 
					 | 
				
			||||||
        it do
 | 
					 | 
				
			||||||
            expect {
 | 
					 | 
				
			||||||
                Puppet::Type.type(:midonet_gateway).new(
 | 
					 | 
				
			||||||
                    :hostname        => Facter['hostname'].value,
 | 
					 | 
				
			||||||
                    :midonet_api_url => 'http://87.23.43.2:8080/midonet-api',
 | 
					 | 
				
			||||||
                    :username        => 'admin',
 | 
					 | 
				
			||||||
                    :password        => 'admin',
 | 
					 | 
				
			||||||
                    :remote_peers    => [ { 'as' => 'fake',
 | 
					 | 
				
			||||||
                                            'ip' => '_198.51.100.1' } ])
 | 
					 | 
				
			||||||
                }.to raise_error(Puppet::ResourceError)
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    context 'on valid router name' do
 | 
					 | 
				
			||||||
        let(:resource) do
 | 
					 | 
				
			||||||
            Puppet::Type.type(:midonet_gateway).new(
 | 
					 | 
				
			||||||
                :hostname        => Facter['hostname'].value,
 | 
					 | 
				
			||||||
                :midonet_api_url => 'http://87.23.43.2:8080/midonet-api',
 | 
					 | 
				
			||||||
                :username        => 'admin',
 | 
					 | 
				
			||||||
                :password        => 'admin',
 | 
					 | 
				
			||||||
                :router          => 'MidoNet Provider Router')
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        it 'assign to it' do
 | 
					 | 
				
			||||||
            expect(resource[:router]).to eq 'MidoNet Provider Router'
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    context 'on invalid advertise network' do
 | 
					 | 
				
			||||||
        it do
 | 
					 | 
				
			||||||
            expect {
 | 
					 | 
				
			||||||
                Puppet::Type.type(:midonet_gateway).new(
 | 
					 | 
				
			||||||
                    :hostname        => Facter['hostname'].value,
 | 
					 | 
				
			||||||
                    :midonet_api_url => 'http://87.23.43.2:8080/midonet-api',
 | 
					 | 
				
			||||||
                    :username        => 'admin',
 | 
					 | 
				
			||||||
                    :password        => 'admin',
 | 
					 | 
				
			||||||
                    :advertise_net   => [ { 'net_prefix' => '_192.0.2.0',
 | 
					 | 
				
			||||||
                                            'net_length' => '24' } ] )
 | 
					 | 
				
			||||||
                }.to raise_error(Puppet::ResourceError)
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										105
									
								
								templates/gateway/create_fake_uplink_l2.sh.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								templates/gateway/create_fake_uplink_l2.sh.erb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Copyright 2016 Midokura SARL
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This script creates the fake uplink assuming that midonet is running
 | 
				
			||||||
 | 
					# correctly.  It takes the IP address CIDR as its argument which gets
 | 
				
			||||||
 | 
					# routed into the MidoNet provider router.  CIDR is defaulted to
 | 
				
			||||||
 | 
					# 172.24.4.0/24 with the gateway 172.24.4.1, but you can override by:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#      ./create_fake_uplink_l2.sh <network_id> 172.24.4.0/24 172.24.4.1
 | 
				
			||||||
 | 
					# or
 | 
				
			||||||
 | 
					#      CIDR=172.24.4.0/24 GATEWAY_IP=172.24.4.1 NETWORK_ID=<network_id> \
 | 
				
			||||||
 | 
					#           ./create_fake_uplink.sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function usage() {
 | 
				
			||||||
 | 
					    echo "Usage: $0 <NETWORK_ID> <CIDR> <GATEWAY_IP>]" 1>&2;
 | 
				
			||||||
 | 
					    exit 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NETWORK_ID=<%= @network_id %>
 | 
				
			||||||
 | 
					CIDR=<%= @cidr %>
 | 
				
			||||||
 | 
					GATEWAY_IP=<%= @gateway_ip %>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ -z "${NETWORK_ID}" ] || [ -z "${CIDR}" ] || [ -z "${GATEWAY_IP}" ]; then
 | 
				
			||||||
 | 
					    usage
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo "NETWORK_ID = $NETWORK_ID"
 | 
				
			||||||
 | 
					echo "CIDR = $CIDR"
 | 
				
			||||||
 | 
					echo "GATEWAY_IP = $GATEWAY_IP"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OLD_IFS=$IFS
 | 
				
			||||||
 | 
					IFS='/'; read -ra CIDR_SPLIT <<< "$CIDR"
 | 
				
			||||||
 | 
					NET_LEN=${CIDR_SPLIT[1]}
 | 
				
			||||||
 | 
					IFS=$OLD_IFS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Save the top directory and source the functions and midorc
 | 
				
			||||||
 | 
					TOP_DIR=$(cd $(dirname "$0") && pwd)
 | 
				
			||||||
 | 
					source $TOP_DIR/midorc
 | 
				
			||||||
 | 
					source $TOP_DIR/functions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set -e
 | 
				
			||||||
 | 
					set -x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Get the host id of the devstack machine
 | 
				
			||||||
 | 
					HOST_ID=$(midonet-cli -e host list | awk '{ print $2 }')
 | 
				
			||||||
 | 
					die_if_not_set $LINENO HOST_ID "FAILED to obtain host id"
 | 
				
			||||||
 | 
					echo "Host: ${HOST_ID}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Check if the default tunnel zone exists
 | 
				
			||||||
 | 
					TZ_NAME='DEFAULT'
 | 
				
			||||||
 | 
					TZ_ID=$(midonet-cli -e list tunnel-zone name $TZ_NAME | awk '{ print $2 }')
 | 
				
			||||||
 | 
					if [[ -z "$TZ_ID" ]]; then
 | 
				
			||||||
 | 
					    TZ_ID=$(midonet-cli -e create tunnel-zone name $TZ_NAME type gre)
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					echo "Tunnel Zone: ${TZ_ID}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Check if the host is a member of the tunnel zone
 | 
				
			||||||
 | 
					TZ_MEMBER=$(midonet-cli -e tunnel-zone $TZ_ID list member host $HOST_ID \
 | 
				
			||||||
 | 
					    address $GATEWAY_IP)
 | 
				
			||||||
 | 
					if [[ -z "$TZ_MEMBER" ]]; then
 | 
				
			||||||
 | 
					    TZ_MEMBER=$(midonet-cli -e tunnel-zone $TZ_ID add member host $HOST_ID \
 | 
				
			||||||
 | 
					        address $GATEWAY_IP)
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					echo "Tunnel Zone Member: ${TZ_MEMBER}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Check if we need to bind - we assume that if 'veth1' is bound, then it must
 | 
				
			||||||
 | 
					# exist, and so does veth0
 | 
				
			||||||
 | 
					BINDING=$(midonet-cli -e host $HOST_ID list binding interface veth1)
 | 
				
			||||||
 | 
					if [[ -z "$BINDING" ]]; then
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Create the veth interfaces
 | 
				
			||||||
 | 
					    sudo ip link add type veth
 | 
				
			||||||
 | 
					    sudo ip addr flush veth0
 | 
				
			||||||
 | 
					    sudo ip addr flush veth1
 | 
				
			||||||
 | 
					    sudo ip link set dev veth0 up
 | 
				
			||||||
 | 
					    sudo ip link set dev veth1 up
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    PORT_ID=$(midonet-cli -e bridge $NETWORK_ID add port)
 | 
				
			||||||
 | 
					    echo "Port: ${PORT_ID}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BINDING=$(midonet-cli -e host $HOST_ID add binding \
 | 
				
			||||||
 | 
					        port bridge $NETWORK_ID port $PORT_ID interface veth1)
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					echo "Binding: ${BINDING}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Add the gateway address to the other veth
 | 
				
			||||||
 | 
					if ! ip addr | grep veth0 | grep $GATEWAY_IP; then
 | 
				
			||||||
 | 
					    sudo ip addr add $GATEWAY_IP/$NET_LEN dev veth0
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo "Successfully created fake uplink"
 | 
				
			||||||
							
								
								
									
										58
									
								
								templates/gateway/midorc.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								templates/gateway/midorc.erb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Copyright 2016 Midokura SARL
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If you want to override these variables, create a file called 'localrc'
 | 
				
			||||||
 | 
					# and place it in the same directory as this file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# rc file(s) location
 | 
				
			||||||
 | 
					RC_DIR=$(cd $(dirname "${BASH_SOURCE:-$0}") && pwd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# allow local overrides of env variables
 | 
				
			||||||
 | 
					if [[ -f $RC_DIR/localrc ]]; then
 | 
				
			||||||
 | 
					    source $RC_DIR/localrc
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# IP address/hostname to use for the services
 | 
				
			||||||
 | 
					SERVICE_HOST=<%= @service_host %>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Directory where all the service files will live
 | 
				
			||||||
 | 
					SERVICE_DIR=<%= @service_dir %>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					USE_SCREEN="True"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# ZK Hosts (comma delimited)
 | 
				
			||||||
 | 
					<%- zkarr = Array.new -%>
 | 
				
			||||||
 | 
					<%- @zookeeper_hosts.each do |s| -%>
 | 
				
			||||||
 | 
					  <%- zkarr.push("#{s['ip']}:#{s['port'] ||= 2181 }") -%>
 | 
				
			||||||
 | 
					<%- end -%>
 | 
				
			||||||
 | 
					ZOOKEEPER_HOSTS=<%= zkarr.join(",") %>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# MidoNet API port and URI
 | 
				
			||||||
 | 
					API_PORT=<%= @api_port %>
 | 
				
			||||||
 | 
					API_URI=http://$SERVICE_HOST:$API_PORT/midonet-api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MIDO_DB_USER=<%= @mido_db_user %>
 | 
				
			||||||
 | 
					MIDO_DB_PASSWORD=<%= @mido_db_password %>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# MidoNet Client
 | 
				
			||||||
 | 
					# --------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Auth variables. They are exported so that you could source this file and
 | 
				
			||||||
 | 
					# run midonet-cli using these credentials
 | 
				
			||||||
 | 
					export MIDO_API_URL=$API_URI
 | 
				
			||||||
 | 
					export MIDO_USER=${MIDO_USER:-admin}
 | 
				
			||||||
 | 
					export MIDO_PROJECT_ID=${MIDO_PROJECT_ID:-admin}
 | 
				
			||||||
 | 
					export MIDO_PASSWORD=${MIDO_PASSWORD:-midonet}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user