[ovs-dev] [PATCH v3 2/4] ovn: OCF script for OVN OVSDB servers
Babu Shanmugam
bschanmu at redhat.com
Wed Sep 28 04:32:18 UTC 2016
Hi Andrew,
I have added "Signed-off-by" on your behalf. Hope you don't mind.
On Wednesday 28 September 2016 10:00 AM, bschanmu at redhat.com wrote:
> From: Babu Shanmugam <bschanmu at redhat.com>
>
> Co-authored-by: Numan Siddique <nusiddiq at redhat.com>
> Signed-off-by: Numan Siddique <nusiddiq at redhat.com>
> Co-authored-by: Andrew Beekhof <abeekhof at redhat.com>
> Signed-off-by: Andrew Beekhof <abeekhof at redhat.com>
> Signed-off-by: Babu Shanmugam <bschanmu at redhat.com>
> ---
> ovn/utilities/automake.mk | 6 +-
> ovn/utilities/ovndb-servers.ocf | 349 ++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 353 insertions(+), 2 deletions(-)
> create mode 100755 ovn/utilities/ovndb-servers.ocf
>
> diff --git a/ovn/utilities/automake.mk b/ovn/utilities/automake.mk
> index b03d125..164cdda 100644
> --- a/ovn/utilities/automake.mk
> +++ b/ovn/utilities/automake.mk
> @@ -1,5 +1,6 @@
> scripts_SCRIPTS += \
> - ovn/utilities/ovn-ctl
> + ovn/utilities/ovn-ctl \
> + ovn/utilities/ovndb-servers.ocf
>
> man_MANS += \
> ovn/utilities/ovn-ctl.8 \
> @@ -20,7 +21,8 @@ EXTRA_DIST += \
> ovn/utilities/ovn-docker-overlay-driver \
> ovn/utilities/ovn-docker-underlay-driver \
> ovn/utilities/ovn-nbctl.8.xml \
> - ovn/utilities/ovn-trace.8.xml
> + ovn/utilities/ovn-trace.8.xml \
> + ovn/utilities/ovndb-servers.ocf
>
> DISTCLEANFILES += \
> ovn/utilities/ovn-ctl.8 \
> diff --git a/ovn/utilities/ovndb-servers.ocf b/ovn/utilities/ovndb-servers.ocf
> new file mode 100755
> index 0000000..bb6c9dc
> --- /dev/null
> +++ b/ovn/utilities/ovndb-servers.ocf
> @@ -0,0 +1,349 @@
> +#!/bin/bash
> +
> +: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
> +. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
> +: ${OVN_CTL_DEFAULT="/usr/share/openvswitch/scripts/ovn-ctl"}
> +CRM_MASTER="${HA_SBIN_DIR}/crm_master -l reboot"
> +CRM_ATTR_REPL_INFO="${HA_SBIN_DIR}/crm_attribute --type crm_config --name OVN_REPL_INFO -s ovn_ovsdb_master_server"
> +OVN_CTL=${OCF_RESKEY_ovn_ctl:-${OVN_CTL_DEFAULT}}
> +MASTER_IP=${OCF_RESKEY_master_ip}
> +
> +# Invalid IP address is an address that can never exist in the network, as
> +# mentioned in rfc-5737. The ovsdb servers connects to this IP address till
> +# a master is promoted and the IPAddr2 resource is started.
> +INVALID_IP_ADDRESS=192.0.2.254
> +
> +host_name=$(ocf_local_nodename)
> +: ${slave_score=5}
> +: ${master_score=10}
> +
> +ovsdb_server_metadata() {
> + cat <<END
> +<?xml version="1.0"?>
> +<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
> +<resource-agent name="ovsdb-server">
> + <version>1.0</version>
> +
> + <longdesc lang="en">
> + This resource manages ovsdb-server.
> + </longdesc>
> +
> + <shortdesc lang="en">
> + Manages ovsdb-server.
> + </shortdesc>
> +
> + <parameters>
> +
> + <parameter name="ovn_ctl" unique="1">
> + <longdesc lang="en">
> + Location to the ovn-ctl script file
> + </longdesc>
> + <shortdesc lang="en">ovn-ctl script</shortdesc>
> + <content type="string" default="${OVN_CTL_DEFAULT}" />
> + </parameter>
> +
> + <parameter name="master_ip" unique="1">
> + <longdesc lang="en">
> + The IP address resource which will be available on the master ovsdb server
> + </longdesc>
> + <shortdesc lang="en">master ip address</shortdesc>
> + <content type="string" />
> + </parameter>
> +
> + </parameters>
> +
> + <actions>
> + <action name="notify" timeout="20s" />
> + <action name="start" timeout="30s" />
> + <action name="stop" timeout="20s" />
> + <action name="promote" timeout="50s" />
> + <action name="demote" timeout="50s" />
> + <action name="monitor" timeout="20s" depth="0" interval="10s" />
> + <action name="meta-data" timeout="5s" />
> + <action name="validate-all" timeout="20s" />
> + </actions>
> +</resource-agent>
> +END
> + exit $OCF_SUCCESS
> +}
> +
> +ovsdb_server_notify() {
> + # requires the notify=true meta resource attribute
> + local type_op="${OCF_RESKEY_CRM_meta_notify_type}-${OCF_RESKEY_CRM_meta_notify_operation}"
> +
> + if [ "$type_op" != "post-promote" ]; then
> + # We are only interested in specific events
> + return $OCF_SUCCESS
> + fi
> +
> + if [ "x${OCF_RESKEY_CRM_meta_notify_promote_uname}" = "x${host_name}" ]; then
> + # Record ourselves so that the agent has a better chance of doing
> + # the right thing at startup
> + ${CRM_ATTR_REPL_INFO} -v "$host_name"
> +
> + else
> + # Synchronize with the new master
> + ${OVN_CTL} demote_ovnnb --db-nb-sync-from-addr=${MASTER_IP}
> + ${OVN_CTL} demote_ovnsb --db-sb-sync-from-addr=${MASTER_IP}
> + fi
> +}
> +
> +ovsdb_server_usage() {
> + cat <<END
> +usage: $0 {start|stop|status|monitor|notify|validate-all|meta-data}
> +
> +Expects to have a fully populated OCF RA-compliant environment set.
> +END
> + exit $1
> +}
> +
> +ovsdb_server_find_active_master() {
> + # Operation sequence is Demote -> Stop -> Start -> Promote
> + # At the point this is run, the only active masters will be
> + # previous masters minus any that were scheduled to be demoted
> +
> + for master in ${OCF_RESKEY_CRM_meta_notify_master_uname}; do
> + found=0
> + for old in ${OCF_RESKEY_CRM_meta_notify_demote_uname}; do
> + if [ $master = $old ]; then
> + found=1
> + fi
> + done
> + if [ $found = 0 ]; then
> + # Rely on master-max=1
> + # Pacemaker will demote any additional ones it finds before starting new copies
> + echo "$master"
> + return
> + fi
> + done
> +
> + local expected_master=$($CRM_ATTR_REPL_INFO --query -q 2>/dev/null)
> + case "x${OCF_RESKEY_CRM_meta_notify_start_uname}x" in
> + *${expected_master}*) echo "${expected_master}";; # The previous master is expected to start
> + esac
> +}
> +
> +ovsdb_server_find_active_peers() {
> + # Do we have any peers that are not stopping
> + for peer in ${OCF_RESKEY_CRM_meta_notify_slave_uname}; do
> + found=0
> + for old in ${OCF_RESKEY_CRM_meta_notify_stop_uname}; do
> + if [ $peer = $old ]; then
> + found=1
> + fi
> + done
> + if [ $found = 0 ]; then
> + # Rely on master-max=1
> + # Pacemaker will demote any additional ones it finds before starting new copies
> + echo "$peer"
> + return
> + fi
> + done
> +}
> +
> +ovsdb_server_master_update() {
> +
> + case $1 in
> + $OCF_SUCCESS)
> + $CRM_MASTER -v ${slave_score};;
> + $OCF_RUNNING_MASTER)
> + $CRM_MASTER -v ${master_score};;
> + #*) $CRM_MASTER -D;;
> + esac
> +}
> +
> +ovsdb_server_monitor() {
> + ovsdb_server_check_status
> + rc=$?
> +
> + ovsdb_server_master_update $rc
> + return $rc
> +}
> +
> +ovsdb_server_check_status() {
> + local sb_status=`${OVN_CTL} status_ovnsb`
> + local nb_status=`${OVN_CTL} status_ovnnb`
> +
> + if [[ $sb_status == "running/backup" && $nb_status == "running/backup" ]]; then
> + return $OCF_SUCCESS
> + fi
> +
> + if [[ $sb_status == "running/active" && $nb_status == "running/active" ]]; then
> + return $OCF_RUNNING_MASTER
> + fi
> +
> + # TODO: What about service running but not in either state above?
> + # Eg. a transient state where one db is "active" and the other
> + # "backup"
> +
> + return $OCF_NOT_RUNNING
> +}
> +
> +ovsdb_server_start() {
> + ovsdb_server_check_status
> + local status=$?
> + # If not in stopped state, return
> + if [ $status -ne $OCF_NOT_RUNNING ]; then
> + return $status
> + fi
> +
> + local present_master=$(ovsdb_server_find_active_master)
> +
> + set ${OVN_CTL}
> +
> + if [ "x${present_master}" = x ]; then
> + # No master detected, or the previous master is not among the
> + # set starting.
> + #
> + # Force all copies to come up as slaves by pointing them into
> + # space and let pacemaker pick one to promote:
> + #
> + set $@ --db-nb-sync-from-addr=${INVALID_IP_ADDRESS} --db-sb-sync-from-addr=${INVALID_IP_ADDRESS}
> +
> + elif [ ${present_master} != ${host_name} ]; then
> + # An existing master is active, connect to it
> + set $@ --db-nb-sync-from-addr=${MASTER_IP} --db-sb-sync-from-addr=${MASTER_IP}
> + fi
> +
> + $@ start_ovsdb
> +
> + while [ 1 = 1 ]; do
> + # It is important that we don't return until we're in a functional state
> + ovsdb_server_monitor
> + rc=$?
> + case $rc in
> + $OCF_SUCCESS) return $rc;;
> + $OCF_RUNNING_MASTER) return $rc;;
> + $OCF_ERR_GENERIC) return $rc;;
> + # Otherwise loop, waiting for the service to start, until
> + # the cluster times the operation out
> + esac
> + done
> +}
> +
> +ovsdb_server_stop() {
> + ovsdb_server_check_status
> + case $? in
> + $OCF_NOT_RUNNING) return ${OCF_SUCCESS};;
> + $OCF_RUNNING_MASTER) return ${OCF_RUNNING_MASTER};;
> + esac
> +
> + ${OVN_CTL} stop_ovsdb
> + ovsdb_server_master_update ${OCF_NOT_RUNNING}
> +
> + while [ 1 = 1 ]; do
> + # It is important that we don't return until we're stopped
> + ovsdb_server_check_status
> + rc=$?
> + case $rc in
> + $OCF_SUCCESS)
> + # Loop, waiting for the service to stop, until the
> + # cluster times the operation out
> + ;;
> + $OCF_NOT_RUNNING)
> + return $OCF_SUCCESS
> + ;;
> + *)
> + return $rc
> + ;;
> + esac
> + done
> +
> + return $OCF_ERR_GENERIC
> +}
> +
> +ovsdb_server_promote() {
> + ovsdb_server_check_status
> + rc=$?
> + case $rc in
> + ${OCF_SUCCESS}) ;;
> + ${OCF_RUNNING_MASTER}) return ${OCF_SUCCESS};;
> + *)
> + ovsdb_server_master_update $OCF_RUNNING_MASTER
> + return ${rc}
> + ;;
> + esac
> +
> + ${OVN_CTL} promote_ovnnb
> + ${OVN_CTL} promote_ovnsb
> +
> + # Record ourselves so that the agent has a better chance of doing
> + # the right thing at startup
> + ${CRM_ATTR_REPL_INFO} -v "$host_name"
> + ovsdb_server_master_update $OCF_RUNNING_MASTER
> + return $OCF_SUCCESS
> +}
> +
> +ovsdb_server_demote() {
> + ovsdb_server_check_status
> + if [ $? = $OCF_NOT_RUNNING ]; then
> + return $OCF_NOT_RUNNING
> + fi
> +
> + local present_master=$(ovsdb_server_find_active_master)
> + local recorded_master=$($CRM_ATTR_REPL_INFO --query -q 2>/dev/null)
> +
> + if [ "x${recorded_master}" = "x${host_name}" -a "x${present_master}" = x ]; then
> + # We are the one and only master
> + # This should be the "normal" case
> + # The only way to be demoted is to call demote_ovn*
> + #
> + # The local database is only reset once we successfully
> + # connect to the peer. So specify one that doesn't exist.
> + #
> + # Eventually a new master will be promoted and we'll resync
> + # using the logic in ovsdb_server_notify()
> + ${OVN_CTL} demote_ovnnb --db-nb-sync-from-addr=${INVALID_IP_ADDRESS}
> + ${OVN_CTL} demote_ovnsb --db-sb-sync-from-addr=${INVALID_IP_ADDRESS}
> +
> + elif [ "x${present_master}" = "x${host_name}" ]; then
> + # Safety check, should never be called
> + #
> + # Never allow sync'ing from ourselves, its a great way to
> + # erase the local DB
> + ${OVN_CTL} demote_ovnnb --db-nb-sync-from-addr=${INVALID_IP_ADDRESS}
> + ${OVN_CTL} demote_ovnsb --db-sb-sync-from-addr=${INVALID_IP_ADDRESS}
> +
> + elif [ "x${present_master}" != x ]; then
> + # There are too many masters and we're an extra one that is
> + # being demoted. Sync to the surviving one
> + ${OVN_CTL} demote_ovnnb --db-nb-sync-from-addr=${MASTER_IP}
> + ${OVN_CTL} demote_ovnsb --db-sb-sync-from-addr=${MASTER_IP}
> +
> + else
> + # For completeness, should never be called
> + #
> + # Something unexpected happened, perhaps CRM_ATTR_REPL_INFO is incorrect
> + ${OVN_CTL} demote_ovnnb --db-nb-sync-from-addr=${INVALID_IP_ADDRESS}
> + ${OVN_CTL} demote_ovnsb --db-sb-sync-from-addr=${INVALID_IP_ADDRESS}
> + fi
> +
> + ovsdb_server_master_update $OCF_SUCCESS
> + return $OCF_SUCCESS
> +}
> +
> +ovsdb_server_validate() {
> + if [ ! -e ${OVN_CTL} ]; then
> + return $OCF_ERR_INSTALLED
> + fi
> + return $OCF_SUCCESS
> +}
> +
> +
> +case $__OCF_ACTION in
> +start) ovsdb_server_start;;
> +stop) ovsdb_server_stop;;
> +promote) ovsdb_server_promote;;
> +demote) ovsdb_server_demote;;
> +start) ovsdb_server_start;;
> +notify) ovsdb_server_notify;;
> +meta-data) ovsdb_server_metadata;;
> +validate-all) ovsdb_server_validate;;
> +status|monitor) ovsdb_server_monitor;;
> +usage|help) ovsdb_server_usage $OCF_SUCCESS;;
> +*) ovsdb_server_usage $OCF_ERR_UNIMPLEMENTED ;;
> +esac
> +
> +rc=$?
> +exit $rc
> +
More information about the dev
mailing list