diff --git a/cts/LSBDummy.in b/cts/LSBDummy.in
index 41cbdb8970..eb2978bc92 100644
--- a/cts/LSBDummy.in
+++ b/cts/LSBDummy.in
@@ -1,102 +1,85 @@
 #!/bin/sh
 #
 #
 #	Dummy LSB RA. Does nothing but touch and remove a state file
 #
-# Copyright 2006-2018 the Pacemaker project contributors
+# Copyright 2006-2021 the Pacemaker project contributors
 #
 # The version control history for this file may have further details.
 #
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of version 2 of the GNU General Public License as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it would be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-#
-# Further, this software is distributed without any warranty that it is
-# free of the rightful claim of any third person regarding infringement
-# or the like.  Any license provided herein, whether implied or
-# otherwise, applies only to this software file.  Patent licenses, if
-# any, provided herein do not apply to combinations of this program with
-# other software, or any other product whatsoever.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write the Free Software Foundation,
-# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
-#
+# This source code is licensed under the GNU General Public License version 2
+# (GPLv2) WITHOUT ANY WARRANTY.
 
 #######################################################################
 # Initialization:
 
 desc="Dummy LSB service"
 . @OCF_ROOT_DIR@/resource.d/heartbeat/.ocf-directories
 : ${HA_VARRUN=/tmp} # Backup in case .ocf-directories doesn't exist
 
 #######################################################################
 
 success()
 {
 	printf "[  OK  ]\r"
 }
 
 failure()
 {
 	printf "[FAILED]\r"
 }
 
 dummy_usage() {
 	cat <<END
 usage: $0 {start|stop|status}
 
 Dummy LSB resource
 END
 }
 
 dummy_start() {
     echo -n "Starting $desc: "
     touch ${state}
     if [ -f ${state} ]; then
 	success
 	return 0
     fi
 
     failure
     return 1
 }
 
 dummy_stop() {
     echo -n "Stopping $desc: "
     rm -f ${state}
     if [ ! -f ${state} ]; then
 	success
 	return 0
     fi
 
     failure
     return 1
 }
 
 dummy_monitor() {
     if [ -f ${state} ]; then
 	echo "Running OK"
 	return 0
     fi
     echo "$desc is stopped"
     return 3
 }
 
 state="${HA_VARRUN}/Dummy-`basename $0`.state"
 
 case $1 in
 start)		dummy_start;;
 stop)		dummy_stop;;
 status)		dummy_monitor;;
 *)		dummy_usage
 		exit 1
 		;;
 esac
 rc=$?
 echo "`basename $0` $1 : $rc"
 exit $rc
diff --git a/daemons/controld/controld_alerts.h b/daemons/controld/controld_alerts.h
index 4fb73d4207..ec5852ab5c 100644
--- a/daemons/controld/controld_alerts.h
+++ b/daemons/controld/controld_alerts.h
@@ -1,20 +1,22 @@
 /*
- * Copyright 2015-2018 Andrew Beekhof <andrew@beekhof.net>
+ * Copyright 2015-2021 the Pacemaker project contributors
+ *
+ * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef CONTROLD_ALERTS__H
 #  define CONTROLD_ALERTS__H
 
 #  include <crm/crm.h>
 #  include <crm/cluster.h>
 #  include <crm/stonith-ng.h>
 
 void crmd_unpack_alerts(xmlNode *alerts);
 void crmd_alert_node_event(crm_node_t *node);
 void crmd_alert_fencing_op(stonith_event_t *e);
 void crmd_alert_resource_op(const char *node, lrmd_event_data_t *op);
 
 #endif
diff --git a/daemons/controld/controld_callbacks.h b/daemons/controld/controld_callbacks.h
index cb3ac150b6..8af99cc996 100644
--- a/daemons/controld/controld_callbacks.h
+++ b/daemons/controld/controld_callbacks.h
@@ -1,21 +1,23 @@
 /*
- * Copyright 2004-2018 Andrew Beekhof <andrew@beekhof.net>
+ * Copyright 2004-2021 the Pacemaker project contributors
+ *
+ * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef CONTROLD_CALLBACKS__H
 #  define CONTROLD_CALLBACKS__H
 
 #include <crm/cluster.h>
 
 extern void crmd_ha_msg_filter(xmlNode * msg);
 
 extern void crmd_cib_connection_destroy(gpointer user_data);
 
 extern gboolean crm_fsa_trigger(gpointer user_data);
 
 extern void peer_update_callback(enum crm_status_type type, crm_node_t * node, const void *data);
 
 #endif
diff --git a/daemons/controld/controld_membership.h b/daemons/controld/controld_membership.h
index 1d348de207..789c330762 100644
--- a/daemons/controld/controld_membership.h
+++ b/daemons/controld/controld_membership.h
@@ -1,24 +1,26 @@
 /*
- * Copyright 2012-2018 Andrew Beekhof <andrew@beekhof.net>
+ * Copyright 2012-2021 the Pacemaker project contributors
+ *
+ * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 #ifndef MEMBERSHIP__H
 #  define MEMBERSHIP__H
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #include <crm/cluster/internal.h>
 
 void post_cache_update(int instance);
 
 extern gboolean check_join_state(enum crmd_fsa_state cur_state, const char *source);
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif
diff --git a/daemons/controld/controld_throttle.h b/daemons/controld/controld_throttle.h
index 9d1b97b89a..cb352e548e 100644
--- a/daemons/controld/controld_throttle.h
+++ b/daemons/controld/controld_throttle.h
@@ -1,27 +1,17 @@
 /*
- * Copyright (C) 2013 Andrew Beekhof <andrew@beekhof.net>
+ * Copyright 2013-2021 the Pacemaker project contributors
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * The version control history for this file may have further details.
  *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * This source code is licensed under the GNU Lesser General Public License
+ * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
-
 void throttle_init(void);
 void throttle_fini(void);
 
 void throttle_set_load_target(float target);
 void throttle_update(xmlNode *xml);
 void throttle_update_job_max(const char *preference);
 int throttle_get_job_limit(const char *node);
 int throttle_get_total_job_limit(int l);
diff --git a/daemons/execd/pacemaker_remote.service.in b/daemons/execd/pacemaker_remote.service.in
index cad70d23bd..1e48d1472e 100644
--- a/daemons/execd/pacemaker_remote.service.in
+++ b/daemons/execd/pacemaker_remote.service.in
@@ -1,52 +1,52 @@
 [Unit]
 Description=Pacemaker Remote executor daemon
 Documentation=man:pacemaker-remoted
-Documentation=https://clusterlabs.org/pacemaker/doc/en-US/Pacemaker/2.0/html-single/Pacemaker_Remote/index.html
+Documentation=https://clusterlabs.org/pacemaker/doc/
 
 # See main pacemaker unit file for descriptions of why these are needed
 After=network.target
 After=time-sync.target
 After=dbus.service
 Wants=dbus.service
 After=resource-agents-deps.target
 Wants=resource-agents-deps.target
 After=syslog.service
 After=rsyslog.service
 
 [Install]
 Alias=pacemaker-remote.service
 WantedBy=multi-user.target
 
 [Service]
 Type=simple
 KillMode=process
 NotifyAccess=none
 EnvironmentFile=-@CONFIGDIR@/pacemaker
 EnvironmentFile=-@CONFIGDIR@/sbd
 
 # Not actually success, but fatal failure -- this ensures no respawn
 SuccessExitStatus=100
 
 ExecStart=@sbindir@/pacemaker-remoted
 
 # Systemd v227 and above can limit the number of processes spawned by a
 # service. That is a bad idea for an HA cluster resource manager, so disable it
 # by default. The administrator can create a local override if they really want
 # a limit. If your systemd version does not support TasksMax, and you want to
 # get rid of the resulting log warnings, comment out this option.
 TasksMax=infinity
 
 # If connected to the cluster and when the service functions properly, it will
 # wait to exit until the cluster notifies it all resources on the remote node
 # have been stopped.  The default of 30min should cover most typical cluster
 # configurations, but it may need an increase to adapt to local conditions
 # (e.g. a large, clustered database could conceivably take longer to stop).
 TimeoutStopSec=30min
 TimeoutStartSec=30s
 
 # Restart options include: no, on-success, on-failure, on-abort or always
 Restart=on-failure
 
 # crm_perror() writes directly to stderr, so ignore it here
 # to avoid double-logging with the wrong format
 StandardError=null
diff --git a/daemons/fenced/fence_legacy.in b/daemons/fenced/fence_legacy.in
index 9f527f7e81..86d20912d5 100755
--- a/daemons/fenced/fence_legacy.in
+++ b/daemons/fenced/fence_legacy.in
@@ -1,272 +1,272 @@
 #!@PYTHON@
 
-__copyright__ = "Copyright 2018-2020 Andrew Beekhof <andrew@beekhof.net>"
+__copyright__ = "Copyright 2018-2021 the Pacemaker project contributors"
 __license__ = "GNU General Public License version 2 or later (GPLv2+) WITHOUT ANY WARRANTY"
 
 import os
 import sys
 import argparse
 import subprocess
 
 VERSION = "1.1.0"
 
 USAGE = """Helper that presents a Pacemaker-style interface for Linux-HA stonith plugins
 
 Should never be invoked by the user directly
 
 
 Usage: fence_legacy [options]
 
 Options:
   -h               usage
   -t <sub agent>   sub agent
   -n <name>        nodename
   -o <string>      Action:  on | off | reset (default) | stat | hostlist
   -s <stonith>     stonith command
   -q               quiet mode
   -V               version"""
 
 META_DATA = """<?xml version="1.0" ?>
 <resource-agent name="fence_pcmk" shortdesc="Helper that presents a Pacemaker-style interface for Linux-HA stonith plugins">
 <longdesc>
 This agent should never be invoked by the user directly.
 </longdesc>
 <vendor-url>https://www.clusterlabs.org/</vendor-url>
 <parameters>
         <parameter name="action" unique="1" required="1">
                 <getopt mixed="-o &lt;action&gt;" />
                 <content type="string" default="disable" />
                 <shortdesc lang="en">Fencing Action</shortdesc>
         </parameter>
         <parameter name="port" unique="1" required="1">
                 <getopt mixed="-n &lt;id&gt;" />
                 <content type="string"  />
                 <shortdesc lang="en">Physical plug number or name of virtual machine</shortdesc>
         </parameter>
         <parameter name="help" unique="1" required="0">
                 <getopt mixed="-h" />
                 <content type="string"  />
                 <shortdesc lang="en">Display help and exit</shortdesc>
         </parameter>
 </parameters>
 <actions>
         <action name="enable" />
         <action name="disable" />
         <action name="reboot" />
         <action name="off" />
         <action name="on" />
         <action name="status" />
         <action name="list" />
         <action name="metadata" />
 </actions>
 </resource-agent>"""
 
 ACTIONS = [
     "on",
     "off",
     "reset",
     "reboot",
     "stat",
     "status",
     "metadata",
     "monitor",
     "list",
     "hostlist",
     "poweroff",
     "poweron"
 ]
 
 # These values must be kept in sync with include/crm/crm.h
 class CrmExit(object):
     OK                   =   0
     ERROR                =   1
     INVALID_PARAM        =   2
 
 
 def parse_cli_options():
     """ Return parsed command-line options (as argparse namespace) """
 
 
     # Don't add standard help option, so we can format it how we want
     parser = argparse.ArgumentParser(add_help=False)
 
     parser.add_argument("-t", metavar="SUBAGENT", dest="subagent",
                         nargs=1, default="none", help="sub-agent")
 
     parser.add_argument("-n", metavar="NODE", dest="node",
                         nargs=1, default="", help="name of target node")
 
     # The help text here is consistent with the original version, though
     # perhaps all actions should be listed.
     parser.add_argument("-o", metavar="ACTION", dest="action",
                         nargs=1, choices=ACTIONS, default="reset",
                         help="action: on | off | reset (default) | stat | hostlist")
 
     parser.add_argument("-s", metavar="COMMAND", dest="command",
                         nargs=1, default="stonith", help="stonith command")
 
     parser.add_argument("-q", dest="quiet", action="store_true",
                         help="quiet mode")
 
     parser.add_argument("-h", "--help", action="store_true",
                         help="show usage and exit")
 
     # Don't use action="version", because that printed to stderr before
     # Python 3.4, and help2man doesn't like that.
     parser.add_argument("-V", "--version", action="store_true",
                         help="show version and exit")
 
     return parser.parse_args()
 
 
 def parse_stdin_options(options):
     """ Update options namespace with options parsed from stdin """
 
     nlines = 0
     for line in sys.stdin:
         # Remove leading and trailing whitespace
         line = line.strip()
 
         # Skip blank lines and comments
         if line == "" or line[0] == "#":
             continue
 
         nlines = nlines + 1
 
         # Parse option name and value (allow whitespace around equals sign)
         try:
             (name, value) = line.split("=", 1)
             name = name.rstrip()
             if name == "":
                 raise ValueError
         except ValueError:
             print("parse error: illegal name in option %d" % nlines,
                   file=sys.stderr)
             sys.exit(CrmExit.INVALID_PARAM)
         value = value.lstrip()
 
         if name == "plugin":
             options.subagent = value
 
         elif name in [ "option", "action" ]:
             options.action = value
 
         elif name == "nodename":
             options.node = value
             os.environ[name] = value
 
         elif name == "stonith":
             options.command = value
 
         elif name != "agent": # agent is used by fenced
             os.environ[name] = value
 
 
 def normalize_options(options):
     """ Use string rather than list of one string """
 
     if not hasattr(options.subagent, "strip"):
         options.subagent = options.subagent[0]
 
     if not hasattr(options.node, "strip"):
         options.node = options.node[0]
 
     if not hasattr(options.action, "strip"):
         options.action = options.action[0]
 
     if not hasattr(options.command, "strip"):
         options.command = options.command[0]
 
 
 def build_command(options):
     """ Return command to execute (as list of arguments) """
 
     if options.action in [ "hostlist", "list" ]:
         extra_args = [ "-l" ]
 
     elif options.action in [ "monitor", "stat", "status" ]:
         extra_args = [ "-S" ]
 
     else:
         if options.node == "":
             if not options.quiet:
                 print("failed: no plug number")
             sys.exit(CrmExit.ERROR)
         extra_args = [ "-T", options.action, options.node ]
 
     return [ options.command, "-t", options.subagent, "-E" ] + extra_args
 
 
 def handle_local_options(options):
     """ Handle options that don't require the fence agent """
 
     if options.help:
         print(USAGE)
         sys.exit(CrmExit.OK)
 
     if options.version:
         print(VERSION)
         sys.exit(CrmExit.OK)
 
 
 def remap_action(options):
     """ Pre-process requested action """
 
     options.action = options.action.lower()
 
     if options.action == "metadata":
         print(META_DATA)
         sys.exit(CrmExit.OK)
 
     elif options.action in [ "hostlist", "list" ]:
         options.quiet = True
 
     # Remap accepted aliases to their actual commands
 
     elif options.action == "reboot":
         options.action = "reset"
 
     elif options.action == "poweron":
         options.action = "on"
 
     elif options.action == "poweroff":
         options.action = "off"
 
 
 def execute_command(options, cmd):
     """ Execute command and return its exit status """
 
     if not options.quiet:
         print("Performing: " + " ".join(cmd))
     return subprocess.call(cmd)
 
 
 def handle_result(options, status):
     """ Process fence agent result """
 
     if status == 0:
         message = "success"
         exitcode = CrmExit.OK
     else:
         message = "failed"
         exitcode = CrmExit.ERROR
     if not options.quiet:
         print("%s: %s %d" % (message, options.node, status))
     sys.exit(exitcode)
 
 
 def main():
     """ Execute an LHA-style fence agent """
 
     options = parse_cli_options()
     handle_local_options(options)
     normalize_options(options)
     parse_stdin_options(options)
     remap_action(options)
     cmd = build_command(options)
     status = execute_command(options, cmd)
     handle_result(options, status)
 
 
 if __name__ == "__main__":
     main()
diff --git a/daemons/pacemakerd/pacemaker.service.in b/daemons/pacemakerd/pacemaker.service.in
index 000f4099d2..b128ddcb3d 100644
--- a/daemons/pacemakerd/pacemaker.service.in
+++ b/daemons/pacemakerd/pacemaker.service.in
@@ -1,97 +1,97 @@
 [Unit]
 Description=Pacemaker High Availability Cluster Manager
 Documentation=man:pacemakerd
-Documentation=https://clusterlabs.org/pacemaker/doc/en-US/Pacemaker/2.0/html-single/Pacemaker_Explained/index.html
+Documentation=https://clusterlabs.org/pacemaker/doc/
 
 # DefaultDependencies takes care of sysinit.target,
 # basic.target, and shutdown.target
 
 # We need networking to bind to a network address. It is recommended not to
 # use Wants or Requires with network.target, and not to use
 # network-online.target for server daemons.
 After=network.target
 
 # Time syncs can make the clock jump backward, which messes with logging
 # and failure timestamps, so wait until it's done.
 After=time-sync.target
 
 # Managing systemd resources requires DBus.
 After=dbus.service
 Wants=dbus.service
 
 # Some OCF resources may have dependencies that aren't managed by the cluster;
 # these must be started before Pacemaker and stopped after it. The
 # resource-agents package provides this target, which lets system adminstrators
 # add drop-ins for those dependencies.
 After=resource-agents-deps.target
 Wants=resource-agents-deps.target
 
 After=syslog.service
 After=rsyslog.service
 After=corosync.service
 Requires=corosync.service
 
 
 [Install]
 WantedBy=multi-user.target
 
 
 [Service]
 Type=simple
 KillMode=process
 NotifyAccess=main
 EnvironmentFile=-@CONFIGDIR@/pacemaker
 EnvironmentFile=-@CONFIGDIR@/sbd
 SuccessExitStatus=100
 
 ExecStart=@sbindir@/pacemakerd -f
 
 # Systemd v227 and above can limit the number of processes spawned by a
 # service. That is a bad idea for an HA cluster resource manager, so disable it
 # by default. The administrator can create a local override if they really want
 # a limit. If your systemd version does not support TasksMax, and you want to
 # get rid of the resulting log warnings, comment out this option.
 TasksMax=infinity
 
 # If pacemakerd doesn't stop, it's probably waiting on a cluster
 # resource.  Sending -KILL will just get the node fenced
 SendSIGKILL=no
 
 # If we ever hit the StartLimitInterval/StartLimitBurst limit, and the
 # admin wants to stop the cluster while pacemakerd is not running, it
 # might be a good idea to enable the ExecStopPost directive below.
 #
 # However, the node will likely end up being fenced as a result, so it's
 # not enabled by default.
 #
 # ExecStopPost=/usr/bin/killall -TERM pacemaker-attrd pacemaker-based \
 #              pacemaker-controld pacemaker-execd pacemaker-fenced \
 #              pacemaker-schedulerd
 
 # If you want Corosync to stop whenever Pacemaker is stopped,
 # uncomment the next line too:
 #
 # ExecStopPost=/bin/sh -c 'pidof pacemaker-controld || killall -TERM corosync'
 
 # Pacemaker will restart along with Corosync if Corosync is stopped while
 # Pacemaker is running.
 # In this case, if you want to be fenced always (if you do not want to restart)
 # uncomment ExecStopPost below.
 # 
 # ExecStopPost=/bin/sh -c 'pidof corosync || \
 #              /usr/bin/systemctl --no-block stop pacemaker'
 
 # When the service functions properly, it will wait to exit until all resources
 # have been stopped on the local node, and potentially across all nodes that
 # are shutting down.  The default of 30min should cover most typical cluster
 # configurations, but it may need an increase to adapt to local conditions
 # (e.g. a large, clustered database could conceivably take longer to stop).
 TimeoutStopSec=30min
 TimeoutStartSec=60s
 
 # Restart options include: no, on-success, on-failure, on-abort or always
 Restart=on-failure
 
 # crm_perror() writes directly to stderr, so ignore it here
 # to avoid double-logging with the wrong format
 StandardError=null
diff --git a/daemons/pacemakerd/pacemakerd.h b/daemons/pacemakerd/pacemakerd.h
index 5f475fd492..ac26aef186 100644
--- a/daemons/pacemakerd/pacemakerd.h
+++ b/daemons/pacemakerd/pacemakerd.h
@@ -1,29 +1,31 @@
 /*
- * Copyright 2010-2018 Andrew Beekhof <andrew@beekhof.net>
+ * Copyright 2010-2021 the Pacemaker project contributors
+ *
+ * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU General Public License version 2
  * or later (GPLv2+) WITHOUT ANY WARRANTY.
  */
 
 #include <crm_internal.h>
 
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/resource.h>
 
 #include <stdint.h>
 
 #include <crm/crm.h>
 #include <crm/common/xml.h>
 
 #define SIZEOF(a)   (sizeof(a) / sizeof(a[0]))
 #define MAX_RESPAWN		100
 
 gboolean mcp_read_config(void);
 
 gboolean cluster_connect_cfg(void);
 gboolean cluster_disconnect_cfg(void);
 void pcmkd_shutdown_corosync(void);
 
 void pcmk_shutdown(int nsig);
diff --git a/doc/Makefile.am b/doc/Makefile.am
index cb3b185865..6a3a065bac 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -1,141 +1,141 @@
 #
 # Copyright 2003-2020 the Pacemaker project contributors
 #
 # The version control history for this file may have further details.
 #
 # This source code is licensed under the GNU General Public License version 2
 # or later (GPLv2+) WITHOUT ANY WARRANTY.
 #
 include $(top_srcdir)/mk/common.mk
 
 # What formats to use for book uploads (i.e. "make www";
 # use BOOK_FORMATS in sphinx subdirectory to change local builds)
 BOOK_FORMATS		?= html singlehtml pdf epub
 
 # Deprecated plaintext documents (dynamically converted to HTML)
 DEPRECATED_ORIGINAL	= crm_fencing.txt
 DEPRECATED_GENERATED	=
 if BUILD_ASCIIDOC
 DEPRECATED_GENERATED	+= $(DEPRECATED_ORIGINAL:%.txt=%.html)
 endif
 DEPRECATED_ALL		= $(DEPRECATED_ORIGINAL) $(DEPRECATED_GENERATED)
 
 doc_DATA		= $(DEPRECATED_ALL)
 noinst_SCRIPTS		= abi-check
 
 SUBDIRS		= sphinx
 
-EXTRA_DIST	= $(DEPRECATED_ORIGINAL) pcs-crmsh-quick-ref.md
+EXTRA_DIST	= $(DEPRECATED_ORIGINAL)
 
 # toplevel rsync destination for www targets (without trailing slash)
 RSYNC_DEST      ?= root@www.clusterlabs.org:/var/www/html
 
 # recursive, preserve symlinks/permissions/times, verbose, compress,
 # don't cross filesystems, sparse, show progress
 RSYNC_OPTS      = -rlptvzxS --progress
 
 LAST_RELEASE	?= Pacemaker-$(VERSION)
 TAG		?= $(shell [ -n "`git tag --points-at HEAD | head -1`" ]	\
 		           && ( git tag --points-at HEAD | head -1 )		\
 			   || git log --pretty=format:%H -n 1 HEAD)
 
 if IS_ASCIIDOC
 ASCIIDOC_HTML_ARGS	= --unsafe --backend=xhtml11
 ASCIIDOC_DBOOK_ARGS	= -b docbook -d book
 else
 ASCIIDOC_HTML_ARGS	= --backend=html5
 ASCIIDOC_DBOOK_ARGS	= -b docbook45 -d book
 endif
 
 %.html: %.txt
 	$(AM_V_GEN)$(ASCIIDOC_CONV) $(ASCIIDOC_HTML_ARGS) --out-file=$@ $< $(PCMK_quiet)
 
 # For Makefile debugging
 .PHONY: vars
 vars:
 	@echo DEPRECATED_ORIGINAL=\'$(DEPRECATED_ORIGINAL)\'
 	@echo DEPRECATED_GENERATED=\'$(DEPRECATED_GENERATED)\'
 	@echo LAST_RELEASE=\'$(LAST_RELEASE)\'
 	@echo TAG=\'$(TAG)\'
 
 
 .PHONY: deprecated-upload
 deprecated-upload: $(DEPRECATED_ALL)
 	rsync $(RSYNC_OPTS) $(DEPRECATED_ALL) "$(RSYNC_DEST)/$(PACKAGE)/doc/"
 
 .PHONY: deprecated-clean
 deprecated-clean:
 	-rm -f $(DEPRECATED_GENERATED)
 
 
 # Annotated source code as HTML
 
 global:
 	$(MAKE) $(AM_MAKEFLAGS) -C .. clean-generic
 	cd .. && gtags -q && htags -sanhIT doc
 
 global-upload: global
 	rsync $(RSYNC_OPTS) HTML/ "$(RSYNC_DEST)/$(PACKAGE)/global/$(TAG)/"
 
 global-clean:
 	-rm -rf HTML
 
 
 # Man pages as HTML
 
 %.8.html: %.8
 	groff -mandoc `man -w ./$<` -T html > $@
 
 %.7.html: %.7
 	groff -mandoc `man -w ./$<` -T html > $@
 
 manhtml:
 	$(MAKE) $(AM_MAKEFLAGS) -C .. all
 	find .. -name "[a-z]*.[78]" -exec $(MAKE) $(AM_MAKEFLAGS) \{\}.html \;
 
 manhtml-upload: manhtml
 	find .. -name "[a-z]*.[78].html" -exec \
 		rsync $(RSYNC_OPTS) \{\} "$(RSYNC_DEST)/$(PACKAGE)/man/" \;
 
 manhtml-clean:
 	-find .. -name "[a-z]*.[78].html" -exec rm \{\} \;
 
 
 # API documentation as HTML
 
 doxygen: Doxyfile
 	doxygen Doxyfile
 
 doxygen-upload: doxygen
 	rsync $(RSYNC_OPTS) api/html/ "$(RSYNC_DEST)/$(PACKAGE)/doxygen/$(TAG)/"
 
 doxygen-clean:
 	-rm -rf api
 
 
 # ABI compatibility report as HTML
 
 abi: abi-check
 	./abi-check $(PACKAGE) $(LAST_RELEASE) $(TAG)
 
 abi-www:
 	export RSYNC_DEST=$(RSYNC_DEST); ./abi-check -u $(PACKAGE) $(LAST_RELEASE) $(TAG)
 
 abi-clean:
 	-rm -rf abi_dumps compat_reports
 
 
 # The main documentation books (which are actually in the sphinx subdirectory)
 books-upload:
 	$(MAKE) $(AM_MAKEFLAGS)	-C sphinx clean
 	$(MAKE) $(AM_MAKEFLAGS)	-C sphinx	\
 		RSYNC_DEST="$(RSYNC_DEST)"	\
 		BOOK_FORMATS="$(BOOK_FORMATS)"	\
 		books-upload
 
 
 # All online documentation (except ABI compatibility, which is run separately)
 .PHONY: www
 www: clean-local deprecated-upload manhtml-upload global-upload doxygen-upload books-upload
 
 clean-local: global-clean manhtml-clean doxygen-clean abi-clean deprecated-clean
diff --git a/doc/pcs-crmsh-quick-ref.md b/doc/pcs-crmsh-quick-ref.md
deleted file mode 100644
index 9fa16d8314..0000000000
--- a/doc/pcs-crmsh-quick-ref.md
+++ /dev/null
@@ -1,365 +0,0 @@
-<!-- (new version of doctoc removed this, so added above:) -->
-<!-- *generated with [DocToc](https://github.com/thlorenz/doctoc-web/)* -->
-<!-- START doctoc generated TOC please keep comment here to allow auto update -->
-<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
-**Table of Contents**
-
-- [General Operations](#general-operations)
-  - [Display the configuration](#display-the-configuration)
-  - [Display the current status](#display-the-current-status)
-  - [Node standby](#node-standby)
-  - [Set cluster property](#set-cluster-property)
-- [Resource manipulation](#resource-manipulation)
-  - [List Resource Agent (RA) classes](#list-resource-agent-ra-classes)
-  - [List available RAs](#list-available-ras)
-  - [List RA info](#list-ra-info)
-  - [Create a resource](#create-a-resource)
-  - [Display a resource](#display-a-resource)
-  - [Display fencing resources](#display-fencing-resources)
-  - [Display Stonith RA info](#display-stonith-ra-info)
-  - [Start a resource](#start-a-resource)
-  - [Stop a resource](#stop-a-resource)
-  - [Remove a resource](#remove-a-resource)
-  - [Modify a resource](#modify-a-resource)
-  - [Delete parameters for a given resource](#delete-parameters-for-a-given-resource)
-  - [List the current resource defaults](#list-the-current-resource-defaults)
-  - [Set resource defaults](#set-resource-defaults)
-  - [List the current operation defaults](#list-the-current-operation-defaults)
-  - [Set operation defaults](#set-operation-defaults)
-  - [Set Colocation](#set-colocation)
-  - [Set ordering](#set-ordering)
-  - [Set preferred location](#set-preferred-location)
-  - [Move resources](#move-resources)
-  - [Resource tracing](#resource-tracing)
-  - [Clear fail counts](#clear-fail-counts)
-  - [Edit fail counts](#edit-fail-counts)
-  - [Handling configuration elements by type](#handling-configuration-elements-by-type)
-  - [Create a clone](#create-a-clone)
-  - [Create a promotable (master/slave) clone](#create-a-promotable-masterslave-clone)
-- [Other operations](#other-operations)
-  - [Batch changes](#batch-changes)
-  - [Template creation](#template-creation)
-  - [Log analysis](#log-analysis)
-  - [Configuration scripts](#configuration-scripts)
-
-<!-- END doctoc generated TOC please keep comment here to allow auto update -->
-
-# General Operations
-
-## Display the configuration
-
-    crmsh # crm configure show xml
-    pcs   # pcs cluster cib
-
-To show a simplified (non-xml) syntax
-
-    crmsh # crm configure show
-    pcs   # pcs config
-    
-## Display the current status
-
-    crmsh # crm status
-    pcs   # pcs status
-
-also
-
-    # crm_mon -1
-
-## Node standby
-
-Put node in standby
-
-    crmsh    # crm node standby pcmk-1
-    pcs-0.9  # pcs cluster standby pcmk-1
-    pcs-0.10 # pcs node standby pcmk-1
-
-Remove node from standby
-
-    crmsh    # crm node online pcmk-1
-    pcs-0.9  # pcs cluster unstandby pcmk-1
-    pcs-0.10 # pcs node unstandby pcmk-1
-
-crm has the ability to set the status on reboot or forever. 
-pcs can apply the change to all the nodes.
-
-## Set cluster property
-
-    crmsh # crm configure property stonith-enabled=false
-    pcs   # pcs property set stonith-enabled=false
-
-# Resource manipulation
-
-## List Resource Agent (RA) classes
-
-    crmsh # crm ra classes
-    pcs   # pcs resource standards
-
-## List available RAs
-
-    crmsh # crm ra list ocf
-    crmsh # crm ra list lsb
-    crmsh # crm ra list service
-    crmsh # crm ra list stonith
-    pcs   # pcs resource agents ocf
-    pcs   # pcs resource agents lsb
-    pcs   # pcs resource agents service
-    pcs   # pcs resource agents stonith
-    pcs   # pcs resource agents
-
-You can also filter by provider
-
-    crmsh # crm ra list ocf pacemaker
-    pcs   # pcs resource agents ocf:pacemaker
-
-## List RA info
-
-    crmsh # crm ra meta IPaddr2
-    pcs   # pcs resource describe IPaddr2
-
-Use any RA name (like IPaddr2) from the list displayed with the previous command
-You can also use the full class:provider:RA format if multiple RAs with the same name are available :
-
-    crmsh # crm ra meta ocf:heartbeat:IPaddr2
-    pcs   # pcs resource describe ocf:heartbeat:IPaddr2
-
-## Create a resource
-
-    crmsh # crm configure primitive ClusterIP ocf:heartbeat:IPaddr2 \
-            params ip=192.168.122.120 cidr_netmask=24 \
-            op monitor interval=30s 
-    pcs   # pcs resource create ClusterIP IPaddr2 ip=192.168.0.120 cidr_netmask=24
-
-The standard and provider (`ocf:heartbeat`) are determined automatically since `IPaddr2` is unique.
-The monitor operation is automatically created based on the agent's metadata.
-
-## Display a resource
-
-    crmsh    # crm configure show
-    pcs-0.9  # pcs resource show --full
-    pcs-0.10 # pcs resource config
-
-crmsh also displays fencing resources. 
-The result can be filtered by supplying a resource name (IE `ClusterIP`):
-
-    crmsh    # crm configure show ClusterIP
-    pcs-0.9  # pcs resource show ClusterIP
-    pcs-0.10 # pcs resource config ClusterIP
-
-crmsh also displays fencing resources. 
-
-## Display fencing resources
-
-    crmsh    # crm resource show
-    pcs-0.9  # pcs stonith show --full
-    pcs-0.10 # pcs stonith config
-
-pcs treats STONITH devices separately.
-
-## Display Stonith RA info
-
-    crmsh # crm ra meta stonith:fence_ipmilan
-    pcs   # pcs stonith describe fence_ipmilan
-
-## Start a resource
-
-    crmsh # crm resource start ClusterIP
-    pcs   # pcs resource enable ClusterIP
-
-## Stop a resource
-
-    crmsh # crm resource stop ClusterIP
-    pcs   # pcs resource disable ClusterIP
-
-## Remove a resource
-
-    crmsh # crm configure delete ClusterIP
-    pcs   # pcs resource delete ClusterIP
-
-## Modify a resource
-
-    crmsh # crm resource param ClusterIP set clusterip_hash=sourceip
-    pcs   # pcs resource update ClusterIP clusterip_hash=sourceip
-
-crmsh also has an `edit` command which edits the simplified CIB syntax
-(same commands as the command line) via a configurable text editor.
-
-    crmsh # crm configure edit ClusterIP
-
-Using the interactive shell mode of crmsh, multiple changes can be
-edited and verified before committing to the live configuration.
-
-    crmsh # crm configure
-    crmsh # edit
-    crmsh # verify
-    crmsh # commit
-
-## Delete parameters for a given resource
-
-    crmsh # crm resource param ClusterIP delete nic
-    pcs   # pcs resource update ClusterIP ip=192.168.0.98 nic=  
-
-## List the current resource defaults
-
-    crmsh # crm configure show type:rsc_defaults
-    pcs   # pcs resource defaults
-
-## Set resource defaults
-
-    crmsh # crm configure rsc_defaults resource-stickiness=100
-    pcs   # pcs resource defaults resource-stickiness=100
-    
-## List the current operation defaults
-
-    crmsh # crm configure show type:op_defaults
-    pcs   # pcs resource op defaults
-
-## Set operation defaults
-
-    crmsh # crm configure op_defaults timeout=240s
-    pcs   # pcs resource op defaults timeout=240s
-
-## Set Colocation
-
-    crmsh # crm configure colocation website-with-ip INFINITY: WebSite ClusterIP
-    pcs   # pcs constraint colocation add ClusterIP with WebSite INFINITY
-
-With roles
-
-    crmsh # crm configure colocation another-ip-with-website inf: AnotherIP WebSite:Master
-    pcs   # pcs constraint colocation add Started AnotherIP with Master WebSite INFINITY
-
-## Set ordering
-
-    crmsh # crm configure order apache-after-ip mandatory: ClusterIP WebSite
-    pcs   # pcs constraint order ClusterIP then WebSite
-
-With roles:
-
-    crmsh # crm configure order ip-after-website Mandatory: WebSite:Master AnotherIP
-    pcs   # pcs constraint order promote WebSite then start AnotherIP
-
-## Set preferred location
-
-    crmsh # crm configure location prefer-pcmk-1 WebSite 50: pcmk-1
-    pcs   # pcs constraint location WebSite prefers pcmk-1=50
-    
-With roles:
-
-    crmsh # crm configure location prefer-pcmk-1 WebSite rule role=Master 50: \#uname eq pcmk-1
-    pcs   # pcs constraint location WebSite rule role=master 50 \#uname eq pcmk-1
-
-## Move resources
-
-    crmsh # crm resource move WebSite pcmk-1
-    pcs   # pcs resource move WebSite pcmk-1
-    
-    crmsh # crm resource unmove WebSite
-    pcs   # pcs resource clear WebSite
-
-A resource can also be moved away from a given node:
-
-    crmsh # crm resource ban Website pcmk-2
-    pcs   # pcs resource ban Website pcmk-2
-
-Remember that moving a resource sets a stickyness to -INF to a given node until unmoved    
-
-## Resource tracing
-
-    crmsh # crm resource trace Website
-
-## Clear fail counts
-
-    crmsh # crm resource cleanup Website
-    pcs   # pcs resource cleanup Website
-
-## Edit fail counts
-
-    crmsh # crm resource failcount Website show pcmk-1
-    crmsh # crm resource failcount Website set pcmk-1 100
-
-## Handling configuration elements by type
-
-pcs deals with constraints differently. These can be manipulated by the command above as well as the following and others
-
-    pcs   # pcs constraint list --full
-    pcs   # pcs constraint remove cli-ban-Website-on-pcmk-1
-
-Removing a constraint in crmsh uses the same command as removing a
-resource.
-
-    crmsh # crm configure remove cli-ban-Website-on-pcmk-1
-
-The `show` and `edit` commands in crmsh can be used to manage
-resources and constraints by type:
-
-    crmsh # crm configure show type:primitive
-    crmsh # crm configure edit type:colocation
-
-## Create a clone
-
-    crmsh # crm configure clone WebIP ClusterIP meta globally-unique=true clone-max=2 clone-node-max=2
-    pcs   # pcs resource clone ClusterIP globally-unique=true clone-max=2 clone-node-max=2
-
-## Create a promotable (master/slave) clone
-
-    crmsh    # crm configure ms WebDataClone WebData \
-               meta master-max=1 master-node-max=1 \
-               clone-max=2 clone-node-max=1 notify=true
-    pcs-0.9  # pcs resource master WebDataClone WebData \
-               master-max=1 master-node-max=1 \
-               clone-max=2 clone-node-max=1 notify=true
-    pcs-0.10 # pcs resource promotable WebData \
-               promoted-max=1 promoted-node-max=1 \
-               clone-max=2 clone-node-max=1 notify=true
-
-# Other operations
-
-## Batch changes
-
-    crmsh # crm
-    crmsh # cib new drbd_cfg
-    crmsh # configure primitive WebData ocf:linbit:drbd params drbd_resource=wwwdata \
-            op monitor interval=60s
-    crmsh # configure ms WebDataClone WebData meta master-max=1 master-node-max=1 \
-            clone-max=2 clone-node-max=1 notify=true
-    crmsh # cib commit drbd_cfg
-    crmsh # quit
-.
-
-    pcs      # pcs cluster cib drbd_cfg
-    pcs      # pcs -f drbd_cfg resource create WebData ocf:linbit:drbd drbd_resource=wwwdata \
-               op monitor interval=60s
-    pcs-0.9  # pcs -f drbd_cfg resource master WebDataClone WebData master-max=1 master-node-max=1 \
-               clone-max=2 clone-node-max=1 notify=true
-    pcs-0.10 # pcs -f drbd_cfg resource promotable WebData promoted-max=1 promoted-node-max=1 \
-               clone-max=2 clone-node-max=1 notify=true
-    pcs      # pcs cluster push cib drbd_cfg
-
-## Template creation
-
-Create a resource template based on a list of primitives of the same
-type
-
-    crmsh # crm configure assist template ClusterIP AdminIP
-
-## Log analysis
-
-Display information about recent cluster events
-
-    crmsh # crm history
-    crmsh # peinputs
-    crmsh # transition pe-input-10
-    crmsh # transition log pe-input-10
-
-## Configuration scripts
-
-Create and apply multiple-step cluster configurations including
-configuration of cluster resources
-
-    crmsh # crm script show apache
-    crmsh # crm script run apache \
-        id=WebSite \
-        install=true \
-        virtual-ip:ip=192.168.0.15 \
-        database:id=WebData \
-        database:install=true
diff --git a/doc/sphinx/Pacemaker_Administration/index.rst b/doc/sphinx/Pacemaker_Administration/index.rst
index 97731245d0..9686863a0a 100644
--- a/doc/sphinx/Pacemaker_Administration/index.rst
+++ b/doc/sphinx/Pacemaker_Administration/index.rst
@@ -1,34 +1,35 @@
 Pacemaker Administration
 ========================
 
 *Managing Pacemaker Clusters*
 
 
 Abstract
 --------
 This document has instructions and tips for system administrators who
 manage high-availability clusters using Pacemaker.
 
 
 Table of Contents
 -----------------
 
 .. toctree::
    :maxdepth: 3
    :numbered:
 
    intro
    installing
    cluster
    configuring
    tools
    troubleshooting
    upgrading
    agents
+   pcs-crmsh
 
 
 Index
 -----
 
 * :ref:`genindex`
 * :ref:`search`
diff --git a/doc/sphinx/Pacemaker_Administration/pcs-crmsh.rst b/doc/sphinx/Pacemaker_Administration/pcs-crmsh.rst
new file mode 100644
index 0000000000..61ab4e6b64
--- /dev/null
+++ b/doc/sphinx/Pacemaker_Administration/pcs-crmsh.rst
@@ -0,0 +1,441 @@
+Quick Comparison of pcs and crm shell
+-------------------------------------
+
+``pcs`` and ``crm shell`` are two popular higher-level command-line interfaces
+to Pacemaker. Each has its own syntax; this chapter gives a quick comparion of
+how to accomplish the same tasks using either one. Some examples also show the
+equivalent command using low-level Pacmaker command-line tools.
+
+These examples show the simplest syntax; see the respective man pages for all
+possible options.
+
+Show Cluster Configuration and Status
+#####################################
+
+.. topic:: Show Configuration (Raw XML)
+
+   .. code-block:: none
+
+      crmsh     # crm configure show xml
+      pcs       # pcs cluster cib
+      pacemaker # cibadmin -Q
+
+.. topic:: Show Configuration (Human-friendly)
+
+   .. code-block:: none
+
+      crmsh # crm configure show
+      pcs   # pcs config
+    
+.. topic:: Show Cluster Status
+
+   .. code-block:: none
+
+      crmsh     # crm status
+      pcs       # pcs status
+      pacemaker # crm_mon -1
+
+Manage Nodes
+############
+
+.. topic:: Put node "pcmk-1" in standby mode
+
+   .. code-block:: none
+
+      crmsh     # crm node standby pcmk-1
+      pcs-0.9   # pcs cluster standby pcmk-1
+      pcs-0.10  # pcs node standby pcmk-1
+      pacemaker # crm_standby -N pcmk-1 -v on
+
+.. topic:: Remove node "pcmk-1" from standby mode
+
+   .. code-block:: none
+
+      crmsh     # crm node online pcmk-1
+      pcs-0.9   # pcs cluster unstandby pcmk-1
+      pcs-0.10  # pcs node unstandby pcmk-1
+      pacemaker # crm_standby -N pcmk-1 -v off
+
+Manage Cluster Properties
+#########################
+
+.. topic:: Set the "stonith-enabled" cluster property to "false"
+
+   .. code-block:: none
+
+      crmsh     # crm configure property stonith-enabled=false
+      pcs       # pcs property set stonith-enabled=false
+      pacemaker # crm_attribute -n stonith-enabled -v false
+
+Show Resource Agent Information
+###############################
+
+.. topic:: List Resource Agent (RA) Classes
+
+   .. code-block:: none
+
+      crmsh    # crm ra classes
+      pcs      # pcs resource standards
+      pacmaker # crm_resource --list-standards
+
+.. topic:: List Available Resource Agents (RAs) by Standard
+
+   .. code-block:: none
+
+      crmsh     # crm ra list ocf
+      pcs       # pcs resource agents ocf
+      pacemaker # crm_resource --list-agents ocf
+
+.. topic:: List Available Resource Agents (RAs) by OCF Provider
+
+   .. code-block:: none
+
+      crmsh     # crm ra list ocf pacemaker
+      pcs       # pcs resource agents ocf:pacemaker
+      pacemaker # crm_resource --list-agents ocf:pacemaker
+
+.. topic:: List Available Resource Agent Parameters
+
+   .. code-block:: none
+
+      crmsh     # crm ra info IPaddr2
+      pcs       # pcs resource describe IPaddr2
+      pacemaker # crm_resource --show-metadata ocf:heartbeat:IPaddr2
+
+You can also use the full ``class:provider:type`` format with crmsh and pcs if
+multiple RAs with the same name are available.
+
+.. topic:: Show Available Fence Agent Parameters
+
+   .. code-block:: none
+
+      crmsh # crm ra info stonith:fence_ipmilan
+      pcs   # pcs stonith describe fence_ipmilan
+
+Manage Resources
+################
+
+.. topic:: Create a Resource
+
+   .. code-block:: none
+
+      crmsh # crm configure primitive ClusterIP ocf:heartbeat:IPaddr2 \
+              params ip=192.168.122.120 cidr_netmask=24 \
+              op monitor interval=30s 
+      pcs   # pcs resource create ClusterIP IPaddr2 ip=192.168.122.120 cidr_netmask=24
+
+pcs determines the standard and provider (``ocf:heartbeat``) automatically
+since ``IPaddr2`` is unique, and automatically creates operations (including
+monitor) based on the agent's meta-data.
+
+.. topic:: Show Configuration of All Resources
+
+   .. code-block:: none
+
+      crmsh    # crm configure show
+      pcs-0.9  # pcs resource show --full
+      pcs-0.10 # pcs resource config
+
+.. topic:: Show Configuration of One Resource
+
+   .. code-block:: none
+
+      crmsh    # crm configure show ClusterIP
+      pcs-0.9  # pcs resource show ClusterIP
+      pcs-0.10 # pcs resource config ClusterIP
+
+.. topic:: Show Configuration of Fencing Resources
+
+   .. code-block:: none
+
+      crmsh    # crm resource status
+      pcs-0.9  # pcs stonith show --full
+      pcs-0.10 # pcs stonith config
+
+.. topic:: Start a Resource
+
+   .. code-block:: none
+
+      crmsh     # crm resource start ClusterIP
+      pcs       # pcs resource enable ClusterIP
+      pacemaker # crm_resource -r ClusterIP --set-parameter target-role --meta -v Started
+
+.. topic:: Stop a Resource
+
+   .. code-block:: none
+
+      crmsh     # crm resource stop ClusterIP
+      pcs       # pcs resource disable ClusterIP
+      pacemaker # crm_resource -r ClusterIP --set-parameter target-role --meta -v Stopped
+
+.. topic:: Remove a Resource
+
+   .. code-block:: none
+
+      crmsh # crm configure delete ClusterIP
+      pcs   # pcs resource delete ClusterIP
+
+.. topic:: Modify a Resource's Instance Parameters
+
+   .. code-block:: none
+
+      crmsh     # crm resource param ClusterIP set clusterip_hash=sourceip
+      pcs       # pcs resource update ClusterIP clusterip_hash=sourceip
+      pacemaker # crm_resource -r ClusterIP --set-parameter clusterip_hash -v sourceip
+
+crmsh also has an `edit` command which edits the simplified CIB syntax
+(same commands as the command line) via a configurable text editor.
+
+.. topic:: Modify a Resource's Instance Parameters Interactively
+
+   .. code-block:: none
+
+      crmsh # crm configure edit ClusterIP
+
+Using the interactive shell mode of crmsh, multiple changes can be
+edited and verified before committing to the live configuration:
+
+.. topic:: Make Multiple Configuration Changes Interactively
+
+   .. code-block:: none
+
+      crmsh # crm configure
+      crmsh # edit
+      crmsh # verify
+      crmsh # commit
+
+.. topic:: Delete a Resource's Instance Parameters
+
+   .. code-block:: none
+
+      crmsh     # crm resource param ClusterIP delete nic
+      pcs       # pcs resource update ClusterIP nic=  
+      pacemaker # crm_resource -r ClusterIP --delete-parameter nic
+
+.. topic:: List Current Resource Defaults
+
+   .. code-block:: none
+
+      crmsh     # crm configure show type:rsc_defaults
+      pcs       # pcs resource defaults
+      pacemaker # cibadmin -Q --scope rsc_defaults
+
+.. topic:: Set Resource Defaults
+
+   .. code-block:: none
+
+      crmsh # crm configure rsc_defaults resource-stickiness=100
+      pcs   # pcs resource defaults resource-stickiness=100
+    
+.. topic:: List Current Operation Defaults
+
+   .. code-block:: none
+
+      crmsh     # crm configure show type:op_defaults
+      pcs       # pcs resource op defaults
+      pacemaker # cibadmin -Q --scope op_defaults
+
+.. topic:: Set Operation Defaults
+
+   .. code-block:: none
+
+      crmsh # crm configure op_defaults timeout=240s
+      pcs   # pcs resource op defaults timeout=240s
+
+.. topic:: Enable Resource Agent Tracing for a Resource
+
+   .. code-block:: none
+
+      crmsh # crm resource trace Website
+
+.. topic:: Clear Fail Counts for a Resource
+
+   .. code-block:: none
+
+      crmsh     # crm resource cleanup Website
+      pcs       # pcs resource cleanup Website
+      pacemaker # crm_resource --cleanup -r Website
+
+.. topic:: Create a Clone Resource
+
+   .. code-block:: none
+
+      crmsh # crm configure clone WebIP ClusterIP meta globally-unique=true clone-max=2 clone-node-max=2
+      pcs   # pcs resource clone ClusterIP globally-unique=true clone-max=2 clone-node-max=2
+
+.. topic:: Create a Promotable Clone Resource
+
+   .. code-block:: none
+
+      crmsh    # crm configure ms WebDataClone WebData \
+                 meta master-max=1 master-node-max=1 \
+                 clone-max=2 clone-node-max=1 notify=true
+      pcs-0.9  # pcs resource master WebDataClone WebData \
+                 master-max=1 master-node-max=1 \
+                 clone-max=2 clone-node-max=1 notify=true
+      pcs-0.10 # pcs resource promotable WebData WebDataClone \
+                 promoted-max=1 promoted-node-max=1 \
+                 clone-max=2 clone-node-max=1 notify=true
+
+pcs will generate the clone name automatically if it is omitted from the
+command line.
+
+
+Manage Constraints
+##################
+
+.. topic:: Create a Colocation Constraint
+
+   .. code-block:: none
+
+      crmsh # crm configure colocation website-with-ip INFINITY: WebSite ClusterIP
+      pcs   # pcs constraint colocation add ClusterIP with WebSite INFINITY
+
+.. topic:: Create a Colocation Constraint Based on Role
+
+   .. code-block:: none
+
+      crmsh # crm configure colocation another-ip-with-website inf: AnotherIP WebSite:Master
+      pcs   # pcs constraint colocation add Started AnotherIP with Promoted WebSite INFINITY
+
+.. topic:: Create an Ordering Constraint
+
+   .. code-block:: none
+
+      crmsh # crm configure order apache-after-ip mandatory: ClusterIP WebSite
+      pcs   # pcs constraint order ClusterIP then WebSite
+
+.. topic:: Create an Ordering Constraint Based on Role
+
+   .. code-block:: none
+
+      crmsh # crm configure order ip-after-website Mandatory: WebSite:Master AnotherIP
+      pcs   # pcs constraint order promote WebSite then start AnotherIP
+
+.. topic:: Create a Location Constraint
+
+   .. code-block:: none
+
+      crmsh # crm configure location prefer-pcmk-1 WebSite 50: pcmk-1
+      pcs   # pcs constraint location WebSite prefers pcmk-1=50
+    
+.. topic:: Create a Location Constraint Based on Role
+
+   .. code-block:: none
+
+      crmsh # crm configure location prefer-pcmk-1 WebSite rule role=Master 50: \#uname eq pcmk-1
+      pcs   # pcs constraint location WebSite rule role=Promoted 50 \#uname eq pcmk-1
+
+.. topic:: Move a Resource to a Specific Node (by Creating a Location Constraint)
+
+   .. code-block:: none
+
+      crmsh     # crm resource move WebSite pcmk-1
+      pcs       # pcs resource move WebSite pcmk-1
+      pacemaker # crm_resource -r WebSite --move -N pcmk-1
+    
+.. topic:: Move a Resource Away from Its Current Node (by Creating a Location Constraint)
+
+   .. code-block:: none
+
+      crmsh     # crm resource ban Website pcmk-2
+      pcs       # pcs resource ban Website pcmk-2
+      pacemaker # crm_resource -r WebSite --move
+
+.. topic:: Remove any Constraints Created by Moving a Resource
+
+   .. code-block:: none
+
+      crmsh     # crm resource unmove WebSite
+      pcs       # pcs resource clear WebSite
+      pacemaker # crm_resource -r WebSite --clear
+
+Advanced Configuration
+######################
+
+Manipulate Configuration Elements by Type
+_________________________________________
+
+.. topic:: List Constraints with IDs
+
+   .. code-block:: none
+
+      pcs   # pcs constraint list --full
+
+.. topic:: Remove Constraint by ID
+
+   .. code-block:: none
+
+      pcs   # pcs constraint remove cli-ban-Website-on-pcmk-1
+      crmsh # crm configure remove cli-ban-Website-on-pcmk-1
+
+crmsh's `show` and `edit` commands can be used to manage resources and
+constraints by type:
+
+.. topic:: Show Configuration Elements
+
+   .. code-block:: none
+
+      crmsh # crm configure show type:primitive
+      crmsh # crm configure edit type:colocation
+
+Batch Changes
+_____________
+
+.. topic:: Make Multiple Changes and Apply Together
+
+   .. code-block:: none
+
+      crmsh # crm
+      crmsh # cib new drbd_cfg
+      crmsh # configure primitive WebData ocf:linbit:drbd params drbd_resource=wwwdata \
+              op monitor interval=60s
+      crmsh # configure ms WebDataClone WebData meta master-max=1 master-node-max=1 \
+              clone-max=2 clone-node-max=1 notify=true
+      crmsh # cib commit drbd_cfg
+      crmsh # quit
+
+      pcs      # pcs cluster cib drbd_cfg
+      pcs      # pcs -f drbd_cfg resource create WebData ocf:linbit:drbd drbd_resource=wwwdata \
+                 op monitor interval=60s
+      pcs-0.9  # pcs -f drbd_cfg resource master WebDataClone WebData \
+                 master-max=1 master-node-max=1 clone-max=2 clone-node-max=1 notify=true
+      pcs-0.10 # pcs -f drbd_cfg resource promotable WebData WebDataClone \
+                 promoted-max=1 promoted-node-max=1 clone-max=2 clone-node-max=1 notify=true
+      pcs      # pcs cluster cib-push drbd_cfg
+
+Template Creation
+_________________
+
+.. topic:: Create Resource Template Based on Existing Primitives of Same Type
+
+   .. code-block:: none
+
+      crmsh # crm configure assist template ClusterIP AdminIP
+
+Log Analysis
+____________
+
+.. topic:: Show Information About Recent Cluster Events
+
+   .. code-block:: none
+
+      crmsh # crm history
+      crmsh # peinputs
+      crmsh # transition pe-input-10
+      crmsh # transition log pe-input-10
+
+Configuration Scripts
+_____________________
+
+.. topic:: Script Multiple-step Cluster Configurations
+
+   .. code-block:: none
+
+      crmsh # crm script show apache
+      crmsh # crm script run apache \
+              id=WebSite \
+              install=true \
+              virtual-ip:ip=192.168.0.15 \
+              database:id=WebData \
+              database:install=true
diff --git a/doc/sphinx/Pacemaker_Administration/upgrading.rst b/doc/sphinx/Pacemaker_Administration/upgrading.rst
index 5b35d3fc04..687a875002 100644
--- a/doc/sphinx/Pacemaker_Administration/upgrading.rst
+++ b/doc/sphinx/Pacemaker_Administration/upgrading.rst
@@ -1,504 +1,535 @@
 .. index:: upgrade
 
 Upgrading a Pacemaker Cluster
 -----------------------------
 
 .. index:: version
 
 Pacemaker Versioning
 ####################
 
 Pacemaker has an overall release version, plus separate version numbers for
 certain internal components.
 
 .. index::
    single: version; release
 
 * **Pacemaker release version:** This version consists of three numbers
   (*x.y.z*).
 
   The major version number (the *x* in *x.y.z*) increases when at least some
   rolling upgrades are not possible from the previous major version. For example,
   a rolling upgrade from 1.0.8 to 1.1.15 should always be supported, but a
   rolling upgrade from 1.0.8 to 2.0.0 may not be possible.
 
   The minor version (the *y* in *x.y.z*) increases when there are significant
   changes in cluster default behavior, tool behavior, and/or the API interface
   (for software that utilizes Pacemaker libraries). The main benefit is to alert
   you to pay closer attention to the release notes, to see if you might be
   affected.
 
   The release counter (the *z* in *x.y.z*) is increased with all public releases
   of Pacemaker, which typically include both bug fixes and new features.
 
 .. index::
    single: feature set
    single: version; feature set
 
 * **CRM feature set:** This version number applies to the communication between
   full cluster nodes, and is used to avoid problems in mixed-version clusters.
 
   The major version number increases when nodes with different versions would not
   work (rolling upgrades are not allowed). The minor version number increases
   when mixed-version clusters are allowed only during rolling upgrades. The
   minor-minor version number is ignored, but allows resource agents to detect
   cluster support for various features. [#]_
 
   Pacemaker ensures that the longest-running node is the cluster's DC. This
   ensures new features are not enabled until all nodes are upgraded to support
   them.
 
 .. index::
    single: version; Pacemaker Remote protocol
 
 * **Pacemaker Remote protocol version:** This version applies to communication
   between a Pacemaker Remote node and the cluster. It increases when an older
   cluster node would have problems hosting the connection to a newer
   Pacemaker Remote node. To avoid these problems, Pacemaker Remote nodes will
   accept connections only from cluster nodes with the same or newer
   Pacemaker Remote protocol version.
 
   Unlike with CRM feature set differences between full cluster nodes,
   mixed Pacemaker Remote protocol versions between Pacemaker Remote nodes and
   full cluster nodes are fine, as long as the Pacemaker Remote nodes have the
   older version. This can be useful, for example, to host a legacy application
   in an older operating system version used as a Pacemaker Remote node.
 
 .. index::
    single: version; XML schema
 
 * **XML schema version:** Pacemaker’s configuration syntax — what's allowed in
   the Configuration Information Base (CIB) — has its own version. This allows
   the configuration syntax to evolve over time while still allowing clusters
   with older configurations to work without change.
 
 
 .. index::
    single: upgrade; methods
 
 Upgrading Cluster Software
 ##########################
 
 There are three approaches to upgrading a cluster, each with advantages and
 disadvantages.
 
 .. table:: **Upgrade Methods**
 
    +---------------------------------------------------+----------+----------+--------+---------+----------+----------+
    | Method                                            | Available| Can be   | Service| Service | Exercises| Allows   |
    |                                                   | between  | used with| outage | recovery| failover | change of|
    |                                                   | all      | Pacemaker| during | during  | logic    | messaging|
    |                                                   | versions | Remote   | upgrade| upgrade |          | layer    |
    |                                                   |          | nodes    |        |         |          | [#]_     |
    +===================================================+==========+==========+========+=========+==========+==========+
    | Complete cluster shutdown                         | yes      | yes      | always | N/A     | no       | yes      |
    +---------------------------------------------------+----------+----------+--------+---------+----------+----------+
    | Rolling (node by node)                            | no       | yes      | always | yes     | yes      | no       |
    |                                                   |          |          | [#]_   |         |          |          |
    +---------------------------------------------------+----------+----------+--------+---------+----------+----------+
    | Detach and reattach                               | yes      | no       | only   | no      | no       | yes      |
    |                                                   |          |          | due to |         |          |          |
    |                                                   |          |          | failure|         |          |          |
    +---------------------------------------------------+----------+----------+--------+---------+----------+----------+
 
 
 .. index::
    single: upgrade; shutdown
 
 Complete Cluster Shutdown
 _________________________
 
 In this scenario, one shuts down all cluster nodes and resources,
 then upgrades all the nodes before restarting the cluster.
 
 #. On each node:
 
    a. Shutdown the cluster software (pacemaker and the messaging layer).
    #. Upgrade the Pacemaker software. This may also include upgrading the
       messaging layer and/or the underlying operating system.
    #. Check the configuration with the ``crm_verify`` tool.
 
 #. On each node:
 
    a. Start the cluster software.
 
 Currently, only Corosync version 2 and greater is supported as the cluster
 layer, but if another stack is supported in the future, the stack does not
 need to be the same one before the upgrade.
 
 One variation of this approach is to build a new cluster on new hosts.
 This allows the new version to be tested beforehand, and minimizes downtime by
 having the new nodes ready to be placed in production as soon as the old nodes
 are shut down.
 
 
 .. index::
    single: upgrade; rolling upgrade
 
 Rolling (node by node)
 ______________________
 
 In this scenario, each node is removed from the cluster, upgraded, and then
 brought back online, until all nodes are running the newest version.
 
 Special considerations when planning a rolling upgrade:
 
 * If you plan to upgrade other cluster software -- such as the messaging layer --
   at the same time, consult that software's documentation for its compatibility
   with a rolling upgrade.
 
 * If the major version number is changing in the Pacemaker version you are
   upgrading to, a rolling upgrade may not be possible. Read the new version's
   release notes (as well the information here) for what limitations may exist.
 
 * If the CRM feature set is changing in the Pacemaker version you are upgrading
   to, you should run a mixed-version cluster only during a small rolling
   upgrade window. If one of the older nodes drops out of the cluster for any
   reason, it will not be able to rejoin until it is upgraded.
 
 * If the Pacemaker Remote protocol version is changing, all cluster nodes
   should be upgraded before upgrading any Pacemaker Remote nodes.
 
 See the ClusterLabs wiki's
 `release calendar <https://wiki.clusterlabs.org/wiki/ReleaseCalendar>`_
 to figure out whether the CRM feature set and/or Pacemaker Remote protocol
 version changed between the the Pacemaker release versions in your rolling
 upgrade.
 
 To perform a rolling upgrade, on each node in turn:
 
 #. Put the node into standby mode, and wait for any active resources
    to be moved cleanly to another node. (This step is optional, but
    allows you to deal with any resource issues before the upgrade.)
 #. Shutdown the cluster software (pacemaker and the messaging layer) on the node.
 #. Upgrade the Pacemaker software. This may also include upgrading the
    messaging layer and/or the underlying operating system.
 #. If this is the first node to be upgraded, check the configuration
    with the ``crm_verify`` tool.
 #. Start the messaging layer.
    This must be the same messaging layer (currently only Corosync version 2 and
    greater is supported) that the rest of the cluster is using.
 
 .. note::
 
    Even if a rolling upgrade from the current version of the cluster to the
    newest version is not directly possible, it may be possible to perform a
    rolling upgrade in multiple steps, by upgrading to an intermediate version
    first.
 
 .. table:: **Version Compatibility Table**
 
    +-------------------------+---------------------------+
    | Version being Installed | Oldest Compatible Version |
    +=========================+===========================+
    | Pacemaker 2.y.z         | Pacemaker 1.1.11 [#]_     |
    +-------------------------+---------------------------+
    | Pacemaker 1.y.z         | Pacemaker 1.0.0           |
    +-------------------------+---------------------------+
    | Pacemaker 0.7.z         | Pacemaker 0.6.z           |
    +-------------------------+---------------------------+
 
 .. index::
    single: upgrade; detach and reattach
 
 Detach and Reattach
 ___________________
 
 The reattach method is a variant of a complete cluster shutdown, where the
 resources are left active and get re-detected when the cluster is restarted.
 
 This method may not be used if the cluster contains any Pacemaker Remote nodes.
 
 #. Tell the cluster to stop managing services. This is required to allow the
    services to remain active after the cluster shuts down.
 
    .. code-block:: none
 
       # crm_attribute --name maintenance-mode --update true
 
 #. On each node, shutdown the cluster software (pacemaker and the messaging
    layer), and upgrade the Pacemaker software. This may also include upgrading
    the messaging layer. While the underlying operating system may be upgraded
    at the same time, that will be more likely to cause outages in the detached
    services (certainly, if a reboot is required).
 #. Check the configuration with the ``crm_verify`` tool.
 #. On each node, start the cluster software.
    Currently, only Corosync version 2 and greater is supported as the cluster
    layer, but if another stack is supported in the future, the stack does not
    need to be the same one before the upgrade.
 #. Verify that the cluster re-detected all resources correctly.
 #. Allow the cluster to resume managing resources again:
 
    .. code-block:: none
 
       # crm_attribute --name maintenance-mode --delete
 
 .. note::
 
    While the goal of the detach-and-reattach method is to avoid disturbing
    running services, resources may still move after the upgrade if any
    resource's location is governed by a rule based on transient node
    attributes. Transient node attributes are erased when the node leaves the
    cluster. A common example is using the ``ocf:pacemaker:ping`` resource to
    set a node attribute used to locate other resources.
 
 .. index::
    pair: upgrade; CIB
 
 Upgrading the Configuration
 ###########################
 
 The CIB schema version can change from one Pacemaker version to another.
 
 After cluster software is upgraded, the cluster will continue to use the older
 schema version that it was previously using. This can be useful, for example,
 when administrators have written tools that modify the configuration, and are
 based on the older syntax. [#]_
 
 However, when using an older syntax, new features may be unavailable, and there
 is a performance impact, since the cluster must do a non-persistent
 configuration upgrade before each transition. So while using the old syntax is
 possible, it is not advisable to continue using it indefinitely.
 
 Even if you wish to continue using the old syntax, it is a good idea to
 follow the upgrade procedure outlined below, except for the last step, to ensure
 that the new software has no problems with your existing configuration (since it
 will perform much the same task internally).
 
 If you are brave, it is sufficient simply to run ``cibadmin --upgrade``.
 
 A more cautious approach would proceed like this:
 
 #. Create a shadow copy of the configuration. The later commands will
    automatically operate on this copy, rather than the live configuration.
 
    .. code-block:: none
 
       # crm_shadow --create shadow
 
 .. index::
    single: configuration; verify
 
 #. Verify the configuration is valid with the new software (which may be
    stricter about syntax mistakes, or may have dropped support for deprecated
    features):
 
    .. code-block:: none
 
       # crm_verify --live-check
 
 #. Fix any errors or warnings.
 #. Perform the upgrade:
 
    .. code-block:: none
 
       # cibadmin --upgrade
 
 #. If this step fails, there are three main possibilities:
 
    a. The configuration was not valid to start with (did you do steps 2 and
       3?).
    #. The transformation failed; `report a bug <https://bugs.clusterlabs.org/>`_.
    #. The transformation was successful but produced an invalid result.
 
    If the result of the transformation is invalid, you may see a number of
    errors from the validation library. If these are not helpful, visit the
    `Validation FAQ wiki page <https://wiki.clusterlabs.org/wiki/Validation_FAQ>`_
    and/or try the manual upgrade procedure described below.
 
 #. Check the changes:
 
    .. code-block:: none
 
       # crm_shadow --diff
 
    If at this point there is anything about the upgrade that you wish to
    fine-tune (for example, to change some of the automatic IDs), now is the
    time to do so:
 
    .. code-block:: none
 
       # crm_shadow --edit
 
    This will open the configuration in your favorite editor (whichever is
    specified by the standard ``$EDITOR`` environment variable).
 
 #. Preview how the cluster will react:
 
    .. code-block:: none
 
       # crm_simulate --live-check --save-dotfile shadow.dot -S
       # dot -Tsvg shadow.dot -o shadow.svg
 
    You can then view shadow.svg with any compatible image viewer or web
    browser. Verify that either no resource actions will occur or that you are
    happy with any that are scheduled.  If the output contains actions you do
    not expect (possibly due to changes to the score calculations), you may need
    to make further manual changes. See :ref:`crm_simulate` for further details
    on how to interpret the output of ``crm_simulate`` and ``dot``.
 
 #. Upload the changes:
 
    .. code-block:: none
 
       # crm_shadow --commit shadow --force
 
    In the unlikely event this step fails, please report a bug.
 
 .. note::
 
    It is also possible to perform the configuration upgrade steps manually:
 
    #. Locate the ``upgrade*.xsl`` conversion scripts provided with the source
       code. These will often be installed in a location such as
       ``/usr/share/pacemaker``, or may be obtained from the
       `source repository <https://github.com/ClusterLabs/pacemaker/tree/master/xml>`_.
           
    #. Run the conversion scripts that apply to your older version, for example:
 
       .. code-block:: none
 
          # xsltproc /path/to/upgrade06.xsl config06.xml > config10.xml
 
    #. Locate the ``pacemaker.rng`` script (from the same location as the xsl
       files).
    #. Check the XML validity:
 
       .. code-block:: none
 
          # xmllint --relaxng /path/to/pacemaker.rng config10.xml
 
    The advantage of this method is that it can be performed without the cluster
    running, and any validation errors are often more informative.
 
 
+What Changed in 2.1
+###################
+
+The Pacemaker 2.1 release is fully backward-compatible in both the CIB XML and
+the C API. Highlights:
+
+* Pacemaker now supports the **OCF Resource Agent API version 1.1**.
+  Most notably, the ``Master`` and ``Slave`` role names have been renamed to
+  ``Promoted`` and ``Unpromoted``.
+
+* Pacemaker now supports colocations where the dependent resource does not
+  affect the primary resource's placement (via a new ``influence`` colocation
+  constraint option and ``critical`` resource meta-attribute). This is intended
+  for cases where a less-important resource must be colocated with an essential
+  resource, but it is preferred to leave the less-important resource stopped if
+  it fails, rather than move both resources.
+
+* If Pacemaker is built with libqb 2.0 or later, the detail log will use
+  **millisecond-resolution timestamps**.
+
+* In addition to crm_mon and stonith_admin, the crmadmin, crm_resource,
+  crm_simulate, and crm_verify commands now support the ``--output-as`` and
+  ``--output-to`` options, including **XML output** (which scripts and
+  higher-level tools are strongly recommended to use instead of trying to parse
+  the text output, which may change from release to release).
+
+For a detailed list of changes, see the release notes and the
+`Pacemaker 2.1 Changes <https://wiki.clusterlabs.org/wiki/Pacemaker_2.1_Changes>`_
+page on the ClusterLabs wiki.
+
+
 What Changed in 2.0
 ###################
 
 The main goal of the 2.0 release was to remove support for deprecated syntax,
 along with some small changes in default configuration behavior and tool
 behavior. Highlights:
 
 * Only Corosync version 2 and greater is now supported as the underlying
   cluster layer. Support for Heartbeat and Corosync 1 (including CMAN) is
   removed.
 
 * The Pacemaker detail log file is now stored in
   ``/var/log/pacemaker/pacemaker.log`` by default.
 
 * The record-pending cluster property now defaults to true, which
   allows status tools such as crm_mon to show operations that are in
   progress.
 
 * Support for a number of deprecated build options, environment variables,
   and configuration settings has been removed.
 
 * The ``master`` tag has been deprecated in favor of using the ``clone`` tag
   with the new ``promotable`` meta-attribute set to ``true``. "Master/slave"
   clone resources are now referred to as "promotable" clone resources.
 
 * The public API for Pacemaker libraries that software applications can use
   has changed significantly.
 
 For a detailed list of changes, see the release notes and the
 `Pacemaker 2.0 Changes <https://wiki.clusterlabs.org/wiki/Pacemaker_2.0_Changes>`_
 page on the ClusterLabs wiki.
 
 
 What Changed in 1.0
 ###################
 
 New
 ___
 
 * Failure timeouts.
 * New section for resource and operation defaults.
 * Tool for making offline configuration changes.
 * ``Rules``, ``instance_attributes``, ``meta_attributes`` and sets of
   operations can be defined once and referenced in multiple places.
 * The CIB now accepts XPath-based create/modify/delete operations. See
   ``cibadmin --help``.
 * Multi-dimensional colocation and ordering constraints.
 * The ability to connect to the CIB from non-cluster machines.
 * Allow recurring actions to be triggered at known times.
 
 
 Changed
 _______
 
 * Syntax
 
   * All resource and cluster options now use dashes (-) instead of underscores
     (_)
   * ``master_slave`` was renamed to ``master``
   * The ``attributes`` container tag was removed
   * The operation field ``pre-req`` has been renamed ``requires``
   * All operations must have an ``interval``, ``start``/``stop`` must have it
     set to zero
 
 * The ``stonith-enabled`` option now defaults to true.
 * The cluster will refuse to start resources if ``stonith-enabled`` is true (or
   unset) and no STONITH resources have been defined
 * The attributes of colocation and ordering constraints were renamed for
   clarity.
 * ``resource-failure-stickiness`` has been replaced by ``migration-threshold``.
 * The parameters for command-line tools have been made consistent
 * Switched to 'RelaxNG' schema validation and 'libxml2' parser
 
   * id fields are now XML IDs which have the following limitations:
 
     * id's cannot contain colons (:)
     * id's cannot begin with a number
     * id's must be globally unique (not just unique for that tag)
 
   * Some fields (such as those in constraints that refer to resources) are
     IDREFs.
 
     This means that they must reference existing resources or objects in
     order for the configuration to be valid.  Removing an object which is
     referenced elsewhere will therefore fail.
 
   * The CIB representation, from which a MD5 digest is calculated to verify
     CIBs on the nodes, has changed.
 
     This means that every CIB update will require a full refresh on any
     upgraded nodes until the cluster is fully upgraded to 1.0. This will result
     in significant performance degradation and it is therefore highly
     inadvisable to run a mixed 1.0/0.6 cluster for any longer than absolutely
     necessary.
 
 * Ping node information no longer needs to be added to ``ha.cf``. Simply
   include the lists of hosts in your ping resource(s).
 
 
 Removed
 _______
 
 
 * Syntax
 
   * It is no longer possible to set resource meta options as top-level
     attributes. Use meta-attributes instead.
   * Resource and operation defaults are no longer read from ``crm_config``.
 
 .. rubric:: Footnotes
 
 .. [#] Before CRM feature set 3.1.0 (Pacemaker 2.0.0), the minor-minor version
        number was treated the same as the minor version.
 
 .. [#] Currently, Corosync version 2 and greater is the only supported cluster
        stack, but other stacks have been supported by past versions, and may be
        supported by future versions.
 
 .. [#] Any active resources will be moved off the node being upgraded, so there
        will be at least a brief outage unless all resources can be migrated
        "live".
 
 .. [#] Rolling upgrades from Pacemaker 1.1.z to 2.y.z are possible only if the
        cluster uses corosync version 2 or greater as its messaging layer, and
        the Cluster Information Base (CIB) uses schema 1.0 or higher in its
        ``validate-with`` property.
 
 .. [#] As of Pacemaker 2.0.0, only schema versions pacemaker-1.0 and higher
        are supported (excluding pacemaker-1.1, which was an experimental schema
        now known as pacemaker-next).
diff --git a/doc/sphinx/Pacemaker_Development/python.rst b/doc/sphinx/Pacemaker_Development/python.rst
index b97919685a..d73dc91566 100644
--- a/doc/sphinx/Pacemaker_Development/python.rst
+++ b/doc/sphinx/Pacemaker_Development/python.rst
@@ -1,81 +1,81 @@
 .. index::
    single: Python
    pair: Python; guidelines
 
 Python Coding Guidelines
 ------------------------
 
 .. index::
    pair: Python; boilerplate
    pair: license; Python
    pair: copyright; Python
 
 .. _s-python-boilerplate:
 
 Python Boilerplate
 ##################
 
 If a Python file is meant to be executed (as opposed to imported), it should
 have a ``.in`` extension, and its first line should be:
 
 .. code-block:: python
 
    #!@PYTHON@
 
 which will be replaced with the appropriate python executable when Pacemaker is
-built. To make that happen, add an ``AC_CONFIG_FILES()`` line to
+built. To make that happen, add an entry to ``CONFIG_FILES_EXEC()`` in
 ``configure.ac``, and add the file name without ``.in`` to ``.gitignore`` (see
 existing examples).
 
 After the above line if any, every Python file should start like this:
 
 .. code-block:: python
 
    """ <BRIEF-DESCRIPTION>
    """
 
    __copyright__ = "Copyright <YYYY[-YYYY]> the Pacemaker project contributors"
    __license__ = "<LICENSE> WITHOUT ANY WARRANTY"
 
 *<BRIEF-DESCRIPTION>* is obviously a brief description of the file's
 purpose. The string may contain any other information typically used in
 a Python file `docstring <https://www.python.org/dev/peps/pep-0257/>`_.
 
 ``<LICENSE>`` should follow the policy set forth in the
 `COPYING <https://github.com/ClusterLabs/pacemaker/blob/master/COPYING>`_ file,
 generally one of "GNU General Public License version 2 or later (GPLv2+)"
 or "GNU Lesser General Public License version 2.1 or later (LGPLv2.1+)".
 
 
 .. index::
    single: Python; 3
    single: Python; version
 
 Python Version Compatibility
 ############################
 
 Pacemaker targets compatibility with Python 3.4 and later.
 
 Do not use features not available in all targeted Python versions. An
 example is the ``subprocess.run()`` function.
 
 
 .. index::
    pair: Python; whitespace
 
 Formatting Python Code
 ######################
 
 * Indentation must be 4 spaces, no tabs.
 * Do not leave trailing whitespace.
 * Lines should be no longer than 80 characters unless limiting line length
   significantly impacts readability. For Python, this limitation is
   flexible since breaking a line often impacts readability, but
   definitely keep it under 120 characters.
 * Where not conflicting with this style guide, it is recommended (but not
   required) to follow `PEP 8 <https://www.python.org/dev/peps/pep-0008/>`_.
 * It is recommended (but not required) to format Python code such that
   ``pylint
   --disable=line-too-long,too-many-lines,too-many-instance-attributes,too-many-arguments,too-many-statements``
   produces minimal complaints (even better if you don't need to disable all
   those checks).
diff --git a/extra/alerts/alert_file.sh.sample b/extra/alerts/alert_file.sh.sample
index e482e934ce..7844c77e60 100644
--- a/extra/alerts/alert_file.sh.sample
+++ b/extra/alerts/alert_file.sh.sample
@@ -1,120 +1,109 @@
 #!/bin/sh
 #
-# Copyright 2015-2017 the Pacemaker project contributors
+# Copyright 2015-2021 the Pacemaker project contributors
 #
 # The version control history for this file may have further details.
 #
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This software is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+# This source code is licensed under the GNU General Public License version 2
+# or later (GPLv2+) WITHOUT ANY WARRANTY.
 #
 ##############################################################################
 # Sample configuration (cib fragment in xml notation)
 # ================================
 # <configuration>
 #   <alerts>
 #     <alert id="alert_sample" path="/path/to/alert_file.sh">
 #       <instance_attributes id="config_for_alert_file">
 #         <nvpair id="debug_option_1" name="debug_exec_order" value="false"/>
 #       </instance_attributes>
 #       <meta_attributes id="config_for_timestamp">
 #         <nvpair id="ts_fmt" name="timestamp-format" value="%H:%M:%S.%06N"/>
 #       </meta_attributes>
 #       <recipient id="logfile_destination" value="/path/to/logfile"/>
 #     </alert>
 #   </alerts>
 # </configuration>
 
 # No one will probably ever see this echo, unless they run the script manually.
 # An alternative would be to log to the system log, or similar. (We can't send
 # this to the configured recipient, because that variable won't be defined in
 # this case either.)
 if [ -z $CRM_alert_version ]; then
     echo "$0 must be run by Pacemaker version 1.1.15 or later"
     exit 0
 fi
 
 # Alert agents must always handle the case where no recipients are defined,
 # even if it's a no-op (a recipient might be added to the configuration later).
 if [ -z "${CRM_alert_recipient}" ]; then
     echo "$0 requires a recipient configured with a full filename path"
     exit 0
 fi
 
 debug_exec_order_default="false"
 
 # Pacemaker passes instance attributes to alert agents as environment variables.
 # It is completely up to the agent what instance attributes to support.
 # Here, we define an instance attribute "debug_exec_order".
 : ${debug_exec_order=${debug_exec_order_default}}
 
 if [ "${debug_exec_order}" = "true" ]; then
     tstamp=`printf "%04d. " "$CRM_alert_node_sequence"`
     if [ ! -z "$CRM_alert_timestamp" ]; then
         tstamp="${tstamp} $CRM_alert_timestamp (`date "+%H:%M:%S.%06N"`): "
     fi
 else
     if [ ! -z "$CRM_alert_timestamp" ]; then
         tstamp="$CRM_alert_timestamp: "
     fi
 fi
 
 case $CRM_alert_kind in
     node)
         echo "${tstamp}Node '${CRM_alert_node}' is now '${CRM_alert_desc}'" >> "${CRM_alert_recipient}"
         ;;
     fencing)
         # Other keys:
         #
         # CRM_alert_node
         # CRM_alert_task
         # CRM_alert_rc
         #
         echo "${tstamp}Fencing ${CRM_alert_desc}" >> "${CRM_alert_recipient}"
         ;;
     resource)
         # Other keys:
         #
         # CRM_alert_target_rc
         # CRM_alert_status
         # CRM_alert_rc
         #
         if [ ${CRM_alert_interval} = "0" ]; then
             CRM_alert_interval=""
         else
             CRM_alert_interval=" (${CRM_alert_interval})"
         fi
 
         if [ ${CRM_alert_target_rc} = "0" ]; then
             CRM_alert_target_rc=""
         else
             CRM_alert_target_rc=" (target: ${CRM_alert_target_rc})"
         fi
 
         case ${CRM_alert_desc} in
             Cancelled) ;;
             *)
                 echo "${tstamp}Resource operation '${CRM_alert_task}${CRM_alert_interval}' for '${CRM_alert_rsc}' on '${CRM_alert_node}': ${CRM_alert_desc}${CRM_alert_target_rc}" >> "${CRM_alert_recipient}"
                 ;;
         esac
         ;;
     attribute)
         #
         echo "${tstamp}Attribute '${CRM_alert_attribute_name}' on node '${CRM_alert_node}' was updated to '${CRM_alert_attribute_value}'" >> "${CRM_alert_recipient}"
         ;;
 
     *)
         echo "${tstamp}Unhandled $CRM_alert_kind alert" >> "${CRM_alert_recipient}"
         env | grep CRM_alert >> "${CRM_alert_recipient}"
         ;;
 esac
diff --git a/extra/alerts/alert_smtp.sh.sample b/extra/alerts/alert_smtp.sh.sample
index b40d7a47b1..5da83ade4a 100644
--- a/extra/alerts/alert_smtp.sh.sample
+++ b/extra/alerts/alert_smtp.sh.sample
@@ -1,117 +1,106 @@
 #!/bin/sh
 #
 # Copyright 2016-2017 the Pacemaker project contributors
 #
 # The version control history for this file may have further details.
 #
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This software is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+# This source code is licensed under the GNU General Public License version 2
+# or later (GPLv2+) WITHOUT ANY WARRANTY.
 #
 ##############################################################################
 #
 # Sample configuration (cib fragment in xml notation)
 # ================================
 # <configuration>
 #   <alerts>
 #     <alert id="smtp_alert" path="/path/to/alert_smtp">
 #       <instance_attributes id="config_for_alert_smtp">
 #         <nvpair id="cluster_name" name="cluster_name" value=""/>
 #         <nvpair id="email_client" name="email_client" value=""/>
 #         <nvpair id="email_sender" name="email_sender" value=""/>
 #       </instance_attributes>
 #       <recipient id="smtp_destination" value="admin@example.com"/>
 #     </alert>
 #   </alerts>
 # </configuration>
 
 email_client_default="sendmail"
 email_sender_default="hacluster"
 email_recipient_default="root"
 
 : ${email_client=${email_client_default}}
 : ${email_sender=${email_sender_default}}
 email_recipient="${CRM_alert_recipient-${email_recipient_default}}"
 
 node_name=`uname -n`
 cluster_name=`crm_attribute --query -n cluster-name -q`
 email_body=`env | grep CRM_alert_`
 
 if [ ! -z "${email_sender##*@*}" ]; then
     email_sender="${email_sender}@${node_name}"
 fi
 
 if [ ! -z "${email_recipient##*@*}" ]; then
     email_recipient="${email_recipient}@${node_name}"
 fi
 
 if [ -z ${CRM_alert_version} ]; then
     email_subject="Pacemaker version 1.1.15 or later is required for alerts"
 else
     case ${CRM_alert_kind} in
         node)
             email_subject="${CRM_alert_timestamp} ${cluster_name}: Node '${CRM_alert_node}' is now '${CRM_alert_desc}'"
             ;;
         fencing)
             email_subject="${CRM_alert_timestamp} ${cluster_name}: Fencing ${CRM_alert_desc}"
             ;;
         resource)
             if [ ${CRM_alert_interval} = "0" ]; then
                 CRM_alert_interval=""
             else
                 CRM_alert_interval=" (${CRM_alert_interval})"
             fi
 
             if [ ${CRM_alert_target_rc} = "0" ]; then
                 CRM_alert_target_rc=""
             else
                 CRM_alert_target_rc=" (target: ${CRM_alert_target_rc})"
             fi
 
             case ${CRM_alert_desc} in
                 Cancelled) ;;
                 *)
                     email_subject="${CRM_alert_timestamp} ${cluster_name}: Resource operation '${CRM_alert_task}${CRM_alert_interval}' for '${CRM_alert_rsc}' on '${CRM_alert_node}': ${CRM_alert_desc}${CRM_alert_target_rc}"
                     ;;
             esac
             ;;
         attribute)
             #
             email_subject="${CRM_alert_timestamp} ${cluster_name}: The '${CRM_alert_attribute_name}' attribute of the '${CRM_alert_node}' node was updated in '${CRM_alert_attribute_value}'"
             ;;
         *)
             email_subject="${CRM_alert_timestamp} ${cluster_name}: Unhandled $CRM_alert_kind alert"
             ;;
 
     esac
 fi
 
 if [ ! -z "${email_subject}" ]; then
     case $email_client in
         # This sample script supports only sendmail for sending the email.
 	# Support for additional senders can easily be added by adding
 	# new cases here.
         sendmail)
             sendmail -t -r "${email_sender}" <<__EOF__
 From: ${email_sender}
 To: ${email_recipient}
 Return-Path: ${email_sender}
 Subject: ${email_subject}
 
 ${email_body}
 __EOF__
             ;;
         *)
             ;;
     esac
 fi
diff --git a/extra/alerts/alert_snmp.sh.sample b/extra/alerts/alert_snmp.sh.sample
index b790a4473e..8354f82308 100644
--- a/extra/alerts/alert_snmp.sh.sample
+++ b/extra/alerts/alert_snmp.sh.sample
@@ -1,182 +1,183 @@
 #!/bin/sh
 #
-# Copyright 2016-2018 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
+# Copyright 2013 Florian CROUZAT <gentoo@floriancrouzat.net>
+# Later changes copyright 2013-2021 the Pacemaker project contributors
 #
 # The version control history for this file may have further details.
 #
 # This source code is licensed under the GNU General Public License version 2
 # or later (GPLv2+) WITHOUT ANY WARRANTY.
 #
 # Description:  Manages a SNMP trap, provided by NTT OSSC as a
 #               script under Pacemaker control
 #
 ##############################################################################
 # This sample script assumes that only users who already have
 # hacluster-equivalent access to the cluster nodes can edit the CIB. Otherwise,
 # a malicious user could run commands as hacluster by inserting shell code into
 # the trap_options or timestamp-format parameters.
 #
 # Sample configuration (cib fragment in xml notation)
 # ================================
 # <configuration>
 #   <alerts>
 #     <alert id="snmp_alert" path="/path/to/alert_snmp.sh">
 #       <instance_attributes id="config_for_alert_snmp">
 #         <nvpair id="trap_node_states" name="trap_node_states" value="all"/>
 #       </instance_attributes>
 #       <meta_attributes id="config_for_timestamp">
 #         <nvpair id="ts_fmt" name="timestamp-format" value="%Y-%m-%d,%H:%M:%S.%01N"/>
 #       </meta_attributes>
 #       <recipient id="snmp_destination" value="192.168.1.2"/>
 #     </alert>
 #   </alerts>
 # </configuration>
 # ================================
 #
 # This uses the official Pacemaker MIB.
 # 1.3.6.1.4.1.32723 has been assigned to the project by IANA:
 # http://www.iana.org/assignments/enterprise-numbers
 
 if [ -z "$CRM_alert_version" ]; then
     echo "$0 must be run by Pacemaker version 1.1.15 or later"
     exit 0
 fi
 
 if [ -z "$CRM_alert_recipient" ]; then
     echo "$0 requires a recipient configured with the SNMP server IP address"
     exit 0
 fi
 
 # Defaults for user-configurable values
 trap_binary_default="/usr/bin/snmptrap"
 trap_version_default="2c"
 trap_options_default=""
 trap_community_default="public"
 trap_node_states_default="all"
 trap_fencing_tasks_default="all"
 trap_resource_tasks_default="all"
 trap_monitor_success_default="false"
 trap_add_hires_timestamp_oid_default="true"
 trap_snmp_persistent_dir_default="/var/lib/pacemaker/snmp"
 trap_ignore_int32_default=2147483647  # maximum Integer32 value
 trap_ignore_string_default="n/a"      # doesn't conflict with valid XML IDs
 
 # Ensure all user-provided variables have values.
 : ${trap_binary=${trap_binary_default}}
 : ${trap_version=${trap_version_default}}
 : ${trap_options=${trap_options_default}}
 : ${trap_community=${trap_community_default}}
 : ${trap_node_states=${trap_node_states_default}}
 : ${trap_fencing_tasks=${trap_fencing_tasks_default}}
 : ${trap_resource_tasks=${trap_resource_tasks_default}}
 : ${trap_monitor_success=${trap_monitor_success_default}}
 : ${trap_add_hires_timestamp_oid=${trap_add_hires_timestamp_oid_default}}
 : ${trap_snmp_persistent_dir=${trap_snmp_persistent_dir_default}}
 : ${trap_ignore_int32=${trap_ignore_int32_default}}
 : ${trap_ignore_string=${trap_ignore_string_default}}
 
 # Ensure all cluster-provided variables have values, regardless of alert type.
 : ${CRM_alert_node=${trap_ignore_string}}
 : ${CRM_alert_rsc=${trap_ignore_string}}
 : ${CRM_alert_task=${trap_ignore_string}}
 : ${CRM_alert_desc=${trap_ignore_string}}
 : ${CRM_alert_status=${trap_ignore_int32}}
 : ${CRM_alert_rc=${trap_ignore_int32}}
 : ${CRM_alert_target_rc=${trap_ignore_int32}}
 : ${CRM_alert_attribute_name=${trap_ignore_string}}
 : ${CRM_alert_attribute_value=${trap_ignore_string}}
 
 # Echo a high-resolution equivalent of the Pacemaker-provided time values
 # using NetSNMP's DateAndTime specification ("%Y-%m-%d,%H:%M:%S.%01N").
 get_system_date() {
     : ${CRM_alert_timestamp_epoch=$(date +%s)}
     : ${CRM_alert_timestamp_usec=0}
 
     YMDHMS=$(date --date="@${CRM_alert_timestamp_epoch}" +"%Y-%m-%d,%H:%M:%S")
     USEC=$(echo ${CRM_alert_timestamp_usec} | cut -b 1)
     echo "${YMDHMS}.${USEC}"
 }
 
 is_in_list() {
     item_list=`echo "$1" | tr ',' ' '`
 
     if [ "${item_list}" = "all" ]; then
         return 0
     else
         for act in $item_list
         do
             act=`echo "$act" | tr A-Z a-z`
             [ "$act" != "$2" ] && continue
             return 0
         done
     fi
     return 1
 }
 
 send_pacemaker_trap() {
     PREFIX="PACEMAKER-MIB::pacemakerNotification"
 
     OUTPUT=$("${trap_binary}" -v "${trap_version}" ${trap_options} \
         -c "${trap_community}" "${CRM_alert_recipient}" "" \
         "${PREFIX}Trap" \
         "${PREFIX}Node"             s "${CRM_alert_node}" \
         "${PREFIX}Resource"         s "${CRM_alert_rsc}" \
         "${PREFIX}Operation"        s "${CRM_alert_task}" \
         "${PREFIX}Description"      s "${CRM_alert_desc}" \
         "${PREFIX}Status"           i "${CRM_alert_status}" \
         "${PREFIX}ReturnCode"       i "${CRM_alert_rc}" \
         "${PREFIX}TargetReturnCode" i "${CRM_alert_target_rc}" \
         "${PREFIX}AttributeName"    s "${CRM_alert_attribute_name}" \
         "${PREFIX}AttributeValue"   s "${CRM_alert_attribute_value}" \
         ${hires_timestamp} 2>&1)
 
     if [ $? -ne 0 ]; then
         echo "${trap_binary} returned error : rc=$? $OUTPUT"
     fi
 }
 
 if [ "${trap_add_hires_timestamp_oid}" = "true" ]; then
     hires_timestamp="HOST-RESOURCES-MIB::hrSystemDate s $(get_system_date)"
 fi
 
 if [ -z ${SNMP_PERSISTENT_DIR} ]; then
     export SNMP_PERSISTENT_DIR="${trap_snmp_persistent_dir}"
     # mkdir for snmp trap tools.
     if [ ! -d ${SNMP_PERSISTENT_DIR} ]; then
         mkdir -p ${SNMP_PERSISTENT_DIR}
     fi
 fi
 
 case "$CRM_alert_kind" in
     node)
         if is_in_list "${trap_node_states}" "${CRM_alert_desc}"; then
             send_pacemaker_trap
         fi
         ;;
 
     fencing)
         if is_in_list "${trap_fencing_tasks}" "${CRM_alert_task}"; then
             send_pacemaker_trap
         fi
         ;;
 
     resource)
         if is_in_list "${trap_resource_tasks}" "${CRM_alert_task}" && \
            [ "${CRM_alert_desc}" != "Cancelled" ] ; then
 
             if [ "${trap_monitor_success}" = "false" ] && \
                [ "${CRM_alert_rc}" = "${CRM_alert_target_rc}" ] && \
                [ "${CRM_alert_task}" = "monitor" ]; then
                 exit 0
             fi
             send_pacemaker_trap
         fi
         ;;
 
     attribute)
         send_pacemaker_trap
         ;;
 
     *)
         ;;
 esac
diff --git a/extra/ansible/docker/roles/docker-host/files/fence_docker_cts b/extra/ansible/docker/roles/docker-host/files/fence_docker_cts
index ae102bfbb7..1b928ff75d 100644
--- a/extra/ansible/docker/roles/docker-host/files/fence_docker_cts
+++ b/extra/ansible/docker/roles/docker-host/files/fence_docker_cts
@@ -1,203 +1,186 @@
 #!/bin/bash
 #
-# Copyright 2014-2015 the Pacemaker project contributors
+# Copyright 2014-2021 the Pacemaker project contributors
 #
 # The version control history for this file may have further details.
 #
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of version 2 of the GNU General Public License as
-# published by the Free Software Foundation.
+# This source code is licensed under the GNU General Public License version 2
+# (GPLv2) WITHOUT ANY WARRANTY.
 #
-# This program is distributed in the hope that it would be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-#
-# Further, this software is distributed without any warranty that it is
-# free of the rightful claim of any third person regarding infringement
-# or the like.  Any license provided herein, whether implied or
-# otherwise, applies only to this software file.  Patent licenses, if
-# any, provided herein do not apply to combinations of this program with
-# other software, or any other product whatsoever.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write the Free Software Foundation,
-# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
-#
-#######################################################################
 
 port=""
 action="list"		 # Default fence action
 
 function usage()
 {
 cat <<EOF
 `basename $0` - A fencing agent for docker containers for testing purposes
  
 Usage: `basename $0` -o|--action [-n|--port] [options]
 Options:
  -h, --help 		This text
  -V, --version		Version information
  
 Commands:
  -o, --action		Action to perform: on|off|reboot|status|monitor
  -n, --port 		The name of a container to control/check
 
 EOF
 	exit 0;
 }
 
 function metadata()
 {
 cat <<EOF
 <?xml version="1.0" ?>
 <resource-agent name="fence_docker_cts" shortdesc="docker fencing agent for testing purposes" >
 	<longdesc>
 		fence_docker_cts fences docker containers for testing purposes.
 	</longdesc>
 	<parameters>
 	<parameter name="action" unique="1" required="0">
 		<getopt mixed="-o, --action=[action]" />
 		<content type="string" default="reboot" />
 		<shortdesc lang="en">Fencing Action</shortdesc>
 	</parameter>
 	<parameter name="port" unique="1" required="0">
 		<getopt mixed="-n, --port=[port]" />
 		<content type="string" />
 		<shortdesc lang="en">The name/id of docker container to control/check</shortdesc>
 	</parameter>
 	</parameters>
 	<actions>
 	<action name="on" />
 	<action name="off" />
 	<action name="reboot" />
 	<action name="status" />
 	<action name="list" />
 	<action name="monitor" />
 	<action name="metadata" />
 	</actions>
 </resource-agent>
 EOF
 	exit 0;
 }
 
 function docker_log() {
 	if ! [ "$action" = "list" ]; then
 		printf "$*\n" 1>&2
 	fi
 }
 
 # stdin option processing
 if [ -z $1 ]; then
 	# If there are no command line args, look for options from stdin
 	while read line; do
 		for word in $(echo "$line"); do
 			case $word in 
 			option=*|action=*) action=`echo $word | sed s/.*=//`;;
 			port=*)			port=`echo $word | sed s/.*=//`;;
 			node=*)			port=`echo $word | sed s/.*=//`;;
 			nodename=*)			port=`echo $word | sed s/.*=//`;;
 			--);;
 			*) docker_log "Invalid command: $word";;
 			esac
 		done
 	done
 fi
 
 # Command line option processing
 while true ; do
 	if [ -z "$1" ]; then
 		break;
 	fi
 	case "$1" in
 	-o|--action|--option) action=$2;	shift; shift;;
 	-n|--port)			port=$2;	  shift; shift;;
 	-V|--version) echo "1.0.0"; exit 0;;
 	--help|-h) 
 		usage;
 		exit 0;;
 	--) shift ; break ;;
 	*) docker_log "Unknown option: $1. See --help for details."; exit 1;;
 	esac
 done
 
 action=`echo $action | tr 'A-Z' 'a-z'`
 case $action in
 	hostlist|list) action=list;;
 	stat|status)   action=status;;
 	restart|reboot|reset)  action=reboot;;
 	poweron|on)	action=start;;
 	poweroff|off)  action=stop;;
 esac
 
 function fence_done() 
 {
 	if [ $1 -eq 0 ]; then
 		docker_log "Operation $action (port=$port) passed"
 	else
 		docker_log "Operation $action (port=$port) failed: $1"
 	fi
 	if [ -z "$returnfile" ]; then
 		rm -f $returnfile
 	fi
 	if [ -z "$helperscript" ]; then
 		rm -f $helperscript
 	fi
 	exit $1
 }
 
 case $action in 
 	metadata) metadata;;
 esac
 
 returnfile=$(mktemp /tmp/fence_docker_cts_returnfileXXXX)
 returnstring=""
 helper_script=$(mktemp /tmp/fence_docker_cts_helperXXXX)
 
 exec_action()
 {
 	echo "#!/bin/bash" > $helper_script
 	echo "sleep 10000" >> $helper_script
 	chmod 755 $helper_script
 	src="$(uname -n)"
 
 	$helper_script "$src" "$action" "$returnfile" "$port" > /dev/null 2>&1 &
 	pid=$!
 	docker_log "waiting on pid $pid"
 	wait $pid > /dev/null 2>&1
 	returnstring=$(cat $returnfile)
 
 	if [ -z "$returnstring" ]; then
 		docker_log "fencing daemon did not respond"
 		fence_done 1
 	fi
 
 	if [ "$returnstring" == "fail" ]; then
 		docker_log "fencing daemon failed to execute action [$action on port $port]"
 		fence_done 1
 	fi
 
 	return 0
 }
 
 exec_action
 case $action in 
 	list)
 		cat $returnfile
 		fence_done 0
 		;;
 
 	status)
 		# 0 if container is on
 		# 1 if container can not be contacted or unknown
 		# 2 if container is off
 		if [ "$returnstring" = "true" ]; then
 			fence_done 0
 		else 
 			fence_done 2
 		fi
 		;;
 	monitor|stop|start|reboot) : ;;
 	*) docker_log "Unknown action: $action"; fence_done 1;;
 esac
 
 fence_done $?
diff --git a/extra/showscores.sh b/extra/showscores.sh
index 09e0777f87..a8647ba21a 100644
--- a/extra/showscores.sh
+++ b/extra/showscores.sh
@@ -1,147 +1,136 @@
 #!/bin/bash
 #
-# Copyright 2008-2017 the Pacemaker project contributors
+# Copyright 2008-2021 the Pacemaker project contributors
 #
 # The version control history for this file may have further details.
 #
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+# This source code is licensed under the GNU General Public License version 2
+# or later (GPLv2+) WITHOUT ANY WARRANTY.
 #
 
 # Display scores of Pacemaker resources
 
 if [ "$1" = "--help" -o "$1" = "-h" ]
 then
 	echo "showscores.sh - basically parsing crm_simulate -Ls."
 	echo "Usage: "
 	echo "$0 (to display score information for all resources on all nodes sorted by resource name)"
 	echo "$0 node (to display score information for all resources on all nodes sorted by nodename)"
 	echo "$0 <resource-id> (to display score information for a specific resource on all nodes)"
 	echo "$0 <resource-id> <nodename> (to display score information for a specific resource on a specific node)"
 	echo "$0 <resource-id> <nodename> singlescore (to display just the score number (not additional info) for a specific resource on a specific node)"
 	exit 0
 fi
 
 tmpfile=/tmp/dkshowscorestmpfiledk
 tmpfile2=/tmp/dkshowscorestmpfile2dk
 
 sortby=1
 if [ "$1" = "node" ] 
 then
 	sortby=3
 fi
 
 export default_stickiness=`crm_attribute -G -n default-resource-stickiness -t rsc_defaults -Q 2>/dev/null`
 if [ -z "$default_stickiness" ]; then default_stickiness=0; fi
 export default_migrationthreshold=`crm_attribute -G -n migration-threshold -t rsc_defaults -Q 2>/dev/null`
 
 if [ -n "$1" -a "$1" != "node" ]
 then
       resource=$1
 fi
 if [ -n "$2" ]
 then
       nodename=$2
 fi
 
 2>&1 crm_simulate -Ls | grep -E "$resource" | grep -E "$nodename" > $tmpfile
 
 parseline() { 
 	if ! echo $*|grep -q "promotion score"; then
 		shift;
 	fi
 	res=$1; shift; shift; shift; shift; 
 	node=$(echo $1|sed 's/:$//'); shift; 
 	score=$1; 
 }
 
 get_stickiness() {
 	res="$1"
 	# get meta attribute resource_stickiness
 	if ! stickiness=`crm_resource -g resource-stickiness -r $res --meta -Q 2>/dev/null`
 	then
 		# if no resource-specific stickiness is confiugured, use the default value
 		stickiness="$default_stickiness"
 	fi
 
 	# get meta attribute resource_failure_stickiness
 	if ! migrationthreshold=`crm_resource -g migration-threshold -r $res --meta -Q 2>/dev/null`
 	then
 		# if that doesn't exist, use the default value
 		migrationthreshold="$default_migrationthreshold"
 	fi	
 }
 
 get_failcount() { #usage $0 res node
         failcount=`crm_failcount -G -r $1 -U $2 -Q 2>/dev/null|grep -o "^[0-9]*$"`
 }
 
 #determine the longest resource name to adjust width of the first column
 max_res_id_len=0
 for res_id in $(tail -n +2 $tmpfile | sed 's/^[a-zA-Z_-]*\:\ //' | cut -d " " -f 1 | sort | uniq); do 
 	res_id_len=$(echo $res_id|wc -c) 
 	[ $res_id_len -gt $max_res_id_len ] && export max_res_id_len=$res_id_len; 
 done
 # we'll later add "_(master)" to master scores, so add 9 chars to max_res_id_len
 max_res_id_len=$(($max_res_id_len+9))
 
 #same for nodenames
 max_node_id_len=0
 for node_id in $(sed 's/^[a-zA-Z_-]*\:\ //' $tmpfile | cut -d " " -f 5 | grep -v "^$" | sort | uniq | sed 's/\://'); do
 	node_id_len=$(echo $node_id|wc -c)
 	[ $node_id_len -gt $max_node_id_len ] && export max_node_id_len=$node_id_len;
 done
 
 # display allocation scores
 grep native_color $tmpfile | while read line
 do
 	unset node res score stickiness failcount migrationthreshold
 	parseline $line
 	get_stickiness $res
 	get_failcount $res $node
 	printf "%-${max_res_id_len}s%-10s%-${max_node_id_len}s%-11s%-9s%-16s\n" $res $score $node $stickiness $failcount $migrationthreshold
 done >> $tmpfile2
 
 # display promotion scores
 grep "promotion score" $tmpfile | while read line
 do
 	unset node res score stickiness failcount migrationthreshold
 	parseline $line
 	# Skip if node=none. Sometimes happens for clones but is internally mapped to another clone instance, so this is skipped
 	[ "$node" = "none" ] && continue
 	inflines=`grep "promotion score" $tmpfile | grep $res | grep 1000000 | wc -l`
 	if [ $inflines -eq 1 ]
 	then
 		# [10:24] <beekhof> the non INFINITY values are the true ones
 		# [10:25] <kleind> except for when the actually resulting score is [-]INFINITY
 		# [10:25] <beekhof> yeah
 		actualline=`grep "promotion score" $tmpfile | grep $res | grep -v 1000000`
 		parseline $actualline
 	fi
 	get_stickiness $res
 	get_failcount $res $node
 	res=$res"_(master)"
 	printf "%-${max_res_id_len}s%-10s%-${max_node_id_len}s%-11s%-9s%-16s\n" $res $score $node $stickiness $failcount $migrationthreshold
 done | sort | uniq >> $tmpfile2
 
 if [ "$3" = "singlescore" ]
 then
 	sed 's/  */ /g' $tmpfile2 | cut -d ' ' -f 2 | tail -n 1
 else
 	# Heading
 	printf "%-${max_res_id_len}s%-10s%-${max_node_id_len}s%-11s%-9s%-16s\n" "Resource" "Score" "Node" "Stickiness" "#Fail" "Migration-Threshold"
 	sort -k $sortby $tmpfile2
 fi
 
 rm -f $tmpfile $tmpfile2
diff --git a/include/crm/cib/Makefile.am b/include/crm/cib/Makefile.am
index 237cdbbb8a..27d23fd2c6 100644
--- a/include/crm/cib/Makefile.am
+++ b/include/crm/cib/Makefile.am
@@ -1,25 +1,14 @@
 #
 # Copyright 2012-2021 the Pacemaker project contributors
 #
 # The version control history for this file may have further details.
 #
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+# This source code is licensed under the GNU General Public License version 2
+# or later (GPLv2+) WITHOUT ANY WARRANTY.
 #
 MAINTAINERCLEANFILES	= Makefile.in
 
 headerdir=$(pkgincludedir)/crm/cib
 
 noinst_HEADERS		= internal.h
 header_HEADERS		= util.h util_compat.h cib_types.h
diff --git a/include/crm/cluster/Makefile.am b/include/crm/cluster/Makefile.am
index b4a0821f5f..96f2bd0eb5 100644
--- a/include/crm/cluster/Makefile.am
+++ b/include/crm/cluster/Makefile.am
@@ -1,25 +1,14 @@
 #
 # Copyright 2012-2021 the Pacemaker project contributors
 #
 # The version control history for this file may have further details.
 #
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+# This source code is licensed under the GNU General Public License version 2
+# or later (GPLv2+) WITHOUT ANY WARRANTY.
 #
 MAINTAINERCLEANFILES    = Makefile.in
 
 headerdir=$(pkgincludedir)/crm/cluster
 
 noinst_HEADERS		= internal.h election_internal.h
 header_HEADERS		= compat.h
diff --git a/include/crm/crm.h b/include/crm/crm.h
index 230a683aa8..dc3e7b7693 100644
--- a/include/crm/crm.h
+++ b/include/crm/crm.h
@@ -1,235 +1,238 @@
 /*
  * Copyright 2004-2021 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef CRM__H
 #  define CRM__H
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
  * \file
  * \brief A dumping ground
  * \ingroup core
  */
 
 #  include <crm_config.h>
 #  include <stdlib.h>
 #  include <glib.h>
 #  include <stdbool.h>
 
 #  include <string.h>
 
 #  include <libxml/tree.h>
 
 #ifndef PCMK_ALLOW_DEPRECATED
 /*!
  * \brief Allow use of deprecated Pacemaker APIs
  *
  * By default, external code using Pacemaker headers is allowed to use
  * deprecated Pacemaker APIs. If PCMK_ALLOW_DEPRECATED is defined to 0 before
  * including any Pacemaker headers, deprecated APIs will be unusable. It is
  * strongly recommended to leave this unchanged for production and release
  * builds, to avoid breakage when users upgrade to new Pacemaker releases that
  * deprecate more APIs. This should be defined to 0 only for development and
  * testing builds when desiring to check for usage of currently deprecated APIs.
  */
 #define PCMK_ALLOW_DEPRECATED 1
 #endif
 
 /*!
  * The CRM feature set assists with compatibility in mixed-version clusters.
  * The major version number increases when nodes with different versions
  * would not work (rolling upgrades are not allowed). The minor version
  * number increases when mixed-version clusters are allowed only during
  * rolling upgrades (a node with the oldest feature set will be elected DC). The
  * minor-minor version number is ignored, but allows resource agents to detect
  * cluster support for various features.
  *
  * The feature set also affects the processing of old saved CIBs (such as for
  * many scheduler regression tests).
  *
  * Particular feature points currently tested by Pacemaker code:
  *
  * >2.1:     Operation updates include timing data
  * >=3.0.5:  XML v2 digests are created
  * >=3.0.8:  Peers do not need acks for cancellations
  * >=3.0.9:  DC will send its own shutdown request to all peers
  *           XML v2 patchsets are created by default
  * >=3.0.13: Fail counts include operation name and interval
  * >=3.2.0:  DC supports PCMK_LRM_OP_INVALID and PCMK_LRM_OP_NOT_CONNECTED
  */
 #  define CRM_FEATURE_SET		"3.9.0"
 
-#  ifndef MAX_NAME
-#    define MAX_NAME	256
-#  endif
+/* Pacemaker's CPG protocols use fixed-width binary fields for the sender and
+ * recipient of a CPG message. This imposes an arbitrary limit on cluster node
+ * names.
+ */
+//! \brief Maximum length of a Corosync cluster node name (in bytes)
+#define MAX_NAME	256
 
 #  define CRM_META			"CRM_meta"
 
 extern char *crm_system_name;
 
 /* *INDENT-OFF* */
 
 // How we represent "infinite" scores
 #  define CRM_SCORE_INFINITY    1000000
 #  define CRM_INFINITY_S        "INFINITY"
 #  define CRM_PLUS_INFINITY_S   "+" CRM_INFINITY_S
 #  define CRM_MINUS_INFINITY_S  "-" CRM_INFINITY_S
 
 /* @COMPAT API < 2.0.0 Deprecated "infinity" aliases
  *
  * INFINITY might be defined elsewhere (e.g. math.h), so undefine it first.
  * This, of course, complicates any attempt to use the other definition in any
  * code that includes this header.
  */
 #  undef INFINITY
 #  define INFINITY_S        "INFINITY"
 #  define MINUS_INFINITY_S "-INFINITY"
 #  define INFINITY        1000000
 
 /* Sub-systems */
 #  define CRM_SYSTEM_DC		"dc"
 #  define CRM_SYSTEM_DCIB		"dcib"
                                         /*  The master CIB */
 #  define CRM_SYSTEM_CIB		"cib"
 #  define CRM_SYSTEM_CRMD		"crmd"
 #  define CRM_SYSTEM_LRMD		"lrmd"
 #  define CRM_SYSTEM_PENGINE	"pengine"
 #  define CRM_SYSTEM_TENGINE	"tengine"
 #  define CRM_SYSTEM_STONITHD	"stonithd"
 #  define CRM_SYSTEM_MCP	"pacemakerd"
 
 // Names of internally generated node attributes
 #  define CRM_ATTR_UNAME            "#uname"
 #  define CRM_ATTR_ID               "#id"
 #  define CRM_ATTR_KIND             "#kind"
 #  define CRM_ATTR_ROLE             "#role"
 #  define CRM_ATTR_IS_DC            "#is_dc"
 #  define CRM_ATTR_CLUSTER_NAME     "#cluster-name"
 #  define CRM_ATTR_SITE_NAME        "#site-name"
 #  define CRM_ATTR_UNFENCED         "#node-unfenced"
 #  define CRM_ATTR_DIGESTS_ALL      "#digests-all"
 #  define CRM_ATTR_DIGESTS_SECURE   "#digests-secure"
 #  define CRM_ATTR_RA_VERSION       "#ra-version"
 #  define CRM_ATTR_PROTOCOL         "#attrd-protocol"
 
 /* Valid operations */
 #  define CRM_OP_NOOP		"noop"
 #  define CRM_OP_JOIN_ANNOUNCE	"join_announce"
 #  define CRM_OP_JOIN_OFFER	"join_offer"
 #  define CRM_OP_JOIN_REQUEST	"join_request"
 #  define CRM_OP_JOIN_ACKNAK	"join_ack_nack"
 #  define CRM_OP_JOIN_CONFIRM	"join_confirm"
 #  define CRM_OP_PING		"ping"
 #  define CRM_OP_NODE_INFO  "node-info"
 #  define CRM_OP_THROTTLE	"throttle"
 #  define CRM_OP_VOTE		"vote"
 #  define CRM_OP_NOVOTE		"no-vote"
 #  define CRM_OP_HELLO		"hello"
 #  define CRM_OP_PECALC		"pe_calc"
 #  define CRM_OP_QUIT		"quit"
 #  define CRM_OP_LOCAL_SHUTDOWN 	"start_shutdown"
 #  define CRM_OP_SHUTDOWN_REQ	"req_shutdown"
 #  define CRM_OP_SHUTDOWN 	"do_shutdown"
 #  define CRM_OP_FENCE	 	"stonith"
 #  define CRM_OP_REGISTER		"register"
 #  define CRM_OP_IPC_FWD		"ipc_fwd"
 #  define CRM_OP_INVOKE_LRM	"lrm_invoke"
 #  define CRM_OP_LRM_REFRESH	"lrm_refresh" /* Deprecated */
 #  define CRM_OP_LRM_QUERY	"lrm_query"
 #  define CRM_OP_LRM_DELETE	"lrm_delete"
 #  define CRM_OP_LRM_FAIL		"lrm_fail"
 #  define CRM_OP_PROBED		"probe_complete"
 #  define CRM_OP_REPROBE		"probe_again"
 #  define CRM_OP_CLEAR_FAILCOUNT  "clear_failcount"
 #  define CRM_OP_REMOTE_STATE     "remote_state"
 #  define CRM_OP_RELAXED_SET  "one-or-more"
 #  define CRM_OP_RELAXED_CLONE  "clone-one-or-more"
 #  define CRM_OP_RM_NODE_CACHE "rm_node_cache"
 #  define CRM_OP_MAINTENANCE_NODES "maintenance_nodes"
 
 /* Possible cluster membership states */
 #  define CRMD_JOINSTATE_DOWN           "down"
 #  define CRMD_JOINSTATE_PENDING        "pending"
 #  define CRMD_JOINSTATE_MEMBER         "member"
 #  define CRMD_JOINSTATE_NACK           "banned"
 
 #  define CRMD_ACTION_DELETE		"delete"
 #  define CRMD_ACTION_CANCEL		"cancel"
 
 #  define CRMD_ACTION_RELOAD		"reload"
 #  define CRMD_ACTION_MIGRATE		"migrate_to"
 #  define CRMD_ACTION_MIGRATED		"migrate_from"
 
 #  define CRMD_ACTION_START		"start"
 #  define CRMD_ACTION_STARTED		"running"
 
 #  define CRMD_ACTION_STOP		"stop"
 #  define CRMD_ACTION_STOPPED		"stopped"
 
 #  define CRMD_ACTION_PROMOTE		"promote"
 #  define CRMD_ACTION_PROMOTED		"promoted"
 #  define CRMD_ACTION_DEMOTE		"demote"
 #  define CRMD_ACTION_DEMOTED		"demoted"
 
 #  define CRMD_ACTION_NOTIFY		"notify"
 #  define CRMD_ACTION_NOTIFIED		"notified"
 
 #  define CRMD_ACTION_STATUS		"monitor"
 #  define CRMD_ACTION_METADATA		"meta-data"
 #  define CRMD_METADATA_CALL_TIMEOUT   30000
 
 /* short names */
 #  define RSC_DELETE	CRMD_ACTION_DELETE
 #  define RSC_CANCEL	CRMD_ACTION_CANCEL
 
 #  define RSC_MIGRATE	CRMD_ACTION_MIGRATE
 #  define RSC_MIGRATED	CRMD_ACTION_MIGRATED
 
 #  define RSC_START	CRMD_ACTION_START
 #  define RSC_STARTED	CRMD_ACTION_STARTED
 
 #  define RSC_STOP	CRMD_ACTION_STOP
 #  define RSC_STOPPED	CRMD_ACTION_STOPPED
 
 #  define RSC_PROMOTE	CRMD_ACTION_PROMOTE
 #  define RSC_PROMOTED	CRMD_ACTION_PROMOTED
 #  define RSC_DEMOTE	CRMD_ACTION_DEMOTE
 #  define RSC_DEMOTED	CRMD_ACTION_DEMOTED
 
 #  define RSC_NOTIFY	CRMD_ACTION_NOTIFY
 #  define RSC_NOTIFIED	CRMD_ACTION_NOTIFIED
 
 #  define RSC_STATUS	CRMD_ACTION_STATUS
 #  define RSC_METADATA	CRMD_ACTION_METADATA
 /* *INDENT-ON* */
 
 #  include <crm/common/logging.h>
 #  include <crm/common/util.h>
 
 static inline const char *
 crm_action_str(const char *task, guint interval_ms) {
     if ((task != NULL) && (interval_ms == 0)
         && (strcasecmp(task, RSC_STATUS) == 0)) {
         return "probe";
     }
     return task;
 }
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
 #include <crm/crm_compat.h>
 #endif
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif
diff --git a/include/crm/fencing/Makefile.am b/include/crm/fencing/Makefile.am
index 92aaad5a2b..8bfc8d818c 100644
--- a/include/crm/fencing/Makefile.am
+++ b/include/crm/fencing/Makefile.am
@@ -1,25 +1,14 @@
 #
 # Copyright 2012-2021 the Pacemaker project contributors
 #
 # The version control history for this file may have further details.
 #
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+# This source code is licensed under the GNU General Public License version 2
+# or later (GPLv2+) WITHOUT ANY WARRANTY.
 #
 MAINTAINERCLEANFILES	= Makefile.in
 
 headerdir=$(pkgincludedir)/crm/fencing
 
 header_HEADERS		= compat.h
 noinst_HEADERS		= internal.h
diff --git a/include/crm/pengine/Makefile.am b/include/crm/pengine/Makefile.am
index 351cef3137..fac60317a3 100644
--- a/include/crm/pengine/Makefile.am
+++ b/include/crm/pengine/Makefile.am
@@ -1,28 +1,17 @@
 #
 # Copyright 2006-2021 the Pacemaker project contributors
 #
 # The version control history for this file may have further details.
 #
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+# This source code is licensed under the GNU General Public License version 2
+# or later (GPLv2+) WITHOUT ANY WARRANTY.
 #
 MAINTAINERCLEANFILES    = Makefile.in
 
 headerdir=$(pkgincludedir)/crm/pengine
 
 noinst_HEADERS		= internal.h remote_internal.h rules_internal.h
 header_HEADERS		= common.h complex.h pe_types.h rules.h status.h \
 			  common_compat.h	\
 			  pe_types_compat.h	\
 			  rules_compat.h
diff --git a/lib/fencing/st_lha.c b/lib/fencing/st_lha.c
index cb610f4d4d..f9fe5f194b 100644
--- a/lib/fencing/st_lha.c
+++ b/lib/fencing/st_lha.c
@@ -1,281 +1,283 @@
 /*
- * Copyright 2004-2018 Andrew Beekhof <andrew@beekhof.net>
+ * Copyright 2004-2021 the Pacemaker project contributors
+ *
+ * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #include <crm_internal.h>
 
 #include <stdio.h>
 #include <stdarg.h>
 #include <string.h>
 #include <errno.h>
 #include <glib.h>
 #include <dlfcn.h>
 
 #include <crm/crm.h>
 #include <crm/stonith-ng.h>
 #include <crm/fencing/internal.h>
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 
 #include <stonith/stonith.h>
 
 #define LHA_STONITH_LIBRARY "libstonith.so.1"
 
 static void *lha_agents_lib = NULL;
 
 static const char META_TEMPLATE[] =
     "<?xml version=\"1.0\"?>\n"
     "<!DOCTYPE resource-agent SYSTEM \"ra-api-1.dtd\">\n"
     "<resource-agent name=\"%s\">\n"
     "  <version>1.0</version>\n"
     "  <longdesc lang=\"en\">\n"
     "%s\n"
     "  </longdesc>\n"
     "  <shortdesc lang=\"en\">%s</shortdesc>\n"
     "%s\n"
     "  <actions>\n"
     "    <action name=\"start\"   timeout=\"20\" />\n"
     "    <action name=\"stop\"    timeout=\"15\" />\n"
     "    <action name=\"status\"  timeout=\"20\" />\n"
     "    <action name=\"monitor\" timeout=\"20\" interval=\"3600\"/>\n"
     "    <action name=\"meta-data\"  timeout=\"15\" />\n"
     "  </actions>\n"
     "  <special tag=\"heartbeat\">\n"
     "    <version>2.0</version>\n" "  </special>\n" "</resource-agent>\n";
 
 static void *
 find_library_function(void **handle, const char *lib, const char *fn)
 {
     void *a_function;
 
     if (*handle == NULL) {
         *handle = dlopen(lib, RTLD_LAZY);
         if ((*handle) == NULL) {
             crm_err("Could not open %s: %s", lib, dlerror());
             return NULL;
         }
     }
 
     a_function = dlsym(*handle, fn);
     if (a_function == NULL) {
         crm_err("Could not find %s in %s: %s", fn, lib, dlerror());
     }
 
     return a_function;
 }
 
 /*!
  * \brief Determine namespace of a fence agent
  *
  * \param[in] agent        Fence agent type
  * \param[in] namespace_s  Name of agent namespace as string, if known
  *
  * \return Namespace of specified agent, as enum value
  */
 bool
 stonith__agent_is_lha(const char *agent)
 {
     Stonith *stonith_obj = NULL;
 
     static gboolean need_init = TRUE;
     static Stonith *(*st_new_fn) (const char *) = NULL;
     static void (*st_del_fn) (Stonith *) = NULL;
 
     if (need_init) {
         need_init = FALSE;
         st_new_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
                                           "stonith_new");
         st_del_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
                                           "stonith_delete");
     }
 
     if (lha_agents_lib && st_new_fn && st_del_fn) {
         stonith_obj = (*st_new_fn) (agent);
         if (stonith_obj) {
             (*st_del_fn) (stonith_obj);
             return TRUE;
         }
     }
     return FALSE;
 }
 
 int
 stonith__list_lha_agents(stonith_key_value_t **devices)
 {
     static gboolean need_init = TRUE;
 
     int count = 0;
     char **entry = NULL;
     char **type_list = NULL;
     static char **(*type_list_fn) (void) = NULL;
     static void (*type_free_fn) (char **) = NULL;
 
     if (need_init) {
         need_init = FALSE;
         type_list_fn = find_library_function(&lha_agents_lib,
                                              LHA_STONITH_LIBRARY,
                                              "stonith_types");
         type_free_fn = find_library_function(&lha_agents_lib,
                                              LHA_STONITH_LIBRARY,
                                              "stonith_free_hostlist");
     }
 
     if (type_list_fn) {
         type_list = (*type_list_fn) ();
     }
 
     for (entry = type_list; entry != NULL && *entry; ++entry) {
         crm_trace("Added: %s", *entry);
         *devices = stonith_key_value_add(*devices, NULL, *entry);
         count++;
     }
     if (type_list && type_free_fn) {
         (*type_free_fn) (type_list);
     }
     return count;
 }
 
 static inline char *
 strdup_null(const char *val)
 {
     if (val) {
         return strdup(val);
     }
     return NULL;
 }
 
 static void
 stonith_plugin(int priority, const char *fmt, ...) G_GNUC_PRINTF(2, 3);
 
 static void
 stonith_plugin(int priority, const char *format, ...)
 {
     int err = errno;
 
     va_list ap;
     int len = 0;
     char *string = NULL;
 
     va_start(ap, format);
 
     len = vasprintf (&string, format, ap);
     va_end(ap);
     CRM_ASSERT(len > 0);
 
     do_crm_log_alias(priority, __FILE__, __func__, __LINE__, "%s", string);
 
     free(string);
     errno = err;
 }
 
 int
 stonith__lha_metadata(const char *agent, int timeout, char **output)
 {
     int rc = 0;
     char *buffer = NULL;
     static const char *no_parameter_info = "<!-- no value -->";
 
     Stonith *stonith_obj = NULL;
 
     static gboolean need_init = TRUE;
     static Stonith *(*st_new_fn) (const char *) = NULL;
     static const char *(*st_info_fn) (Stonith *, int) = NULL;
     static void (*st_del_fn) (Stonith *) = NULL;
     static void (*st_log_fn) (Stonith *, PILLogFun) = NULL;
 
     if (need_init) {
         need_init = FALSE;
         st_new_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
                                           "stonith_new");
         st_del_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
                                           "stonith_delete");
         st_log_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
                                           "stonith_set_log");
         st_info_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
                                            "stonith_get_info");
     }
 
     if (lha_agents_lib && st_new_fn && st_del_fn && st_info_fn && st_log_fn) {
         char *xml_meta_longdesc = NULL;
         char *xml_meta_shortdesc = NULL;
 
         char *meta_param = NULL;
         char *meta_longdesc = NULL;
         char *meta_shortdesc = NULL;
 
         stonith_obj = (*st_new_fn) (agent);
         if (stonith_obj) {
             (*st_log_fn) (stonith_obj, (PILLogFun) & stonith_plugin);
             meta_longdesc = strdup_null((*st_info_fn) (stonith_obj, ST_DEVICEDESCR));
             if (meta_longdesc == NULL) {
                 crm_warn("no long description in %s's metadata.", agent);
                 meta_longdesc = strdup(no_parameter_info);
             }
 
             meta_shortdesc = strdup_null((*st_info_fn) (stonith_obj, ST_DEVICEID));
             if (meta_shortdesc == NULL) {
                 crm_warn("no short description in %s's metadata.", agent);
                 meta_shortdesc = strdup(no_parameter_info);
             }
 
             meta_param = strdup_null((*st_info_fn) (stonith_obj, ST_CONF_XML));
             if (meta_param == NULL) {
                 crm_warn("no list of parameters in %s's metadata.", agent);
                 meta_param = strdup(no_parameter_info);
             }
             (*st_del_fn) (stonith_obj);
         } else {
             errno = EINVAL;
             crm_perror(LOG_ERR, "Agent %s not found", agent);
             return -EINVAL;
         }
 
         xml_meta_longdesc =
             (char *)xmlEncodeEntitiesReentrant(NULL, (const unsigned char *)meta_longdesc);
         xml_meta_shortdesc =
             (char *)xmlEncodeEntitiesReentrant(NULL, (const unsigned char *)meta_shortdesc);
 
         buffer = crm_strdup_printf(META_TEMPLATE, agent, xml_meta_longdesc,
                                    xml_meta_shortdesc, meta_param);
 
         xmlFree(xml_meta_longdesc);
         xmlFree(xml_meta_shortdesc);
 
         free(meta_shortdesc);
         free(meta_longdesc);
         free(meta_param);
     }
     if (output) {
         *output = buffer;
     } else {
         free(buffer);
     }
     return rc;
 }
 
 /* Implement a dummy function that uses -lpils so that linkers don't drop the
  * reference.
  */
 
 #include <pils/plugin.h>
 
 const char *i_hate_pils(int rc);
 
 const char *
 i_hate_pils(int rc)
 {
     return PIL_strerror(rc);
 }
 
 int
 stonith__lha_validate(stonith_t *st, int call_options, const char *target,
                       const char *agent, GHashTable *params, int timeout,
                       char **output, char **error_output)
 {
     errno = EOPNOTSUPP;
     crm_perror(LOG_ERR, "Cannot validate Linux-HA fence agents");
     return -EOPNOTSUPP;
 }
diff --git a/lib/pacemaker/pcmk_cluster_queries.c b/lib/pacemaker/pcmk_cluster_queries.c
index 0bb399edae..7dd9032987 100644
--- a/lib/pacemaker/pcmk_cluster_queries.c
+++ b/lib/pacemaker/pcmk_cluster_queries.c
@@ -1,499 +1,508 @@
+/*
+ * Copyright 2020-2021 the Pacemaker project contributors
+ *
+ * The version control history for this file may have further details.
+ *
+ * This source code is licensed under the GNU Lesser General Public License
+ * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
+ */
+
 #include <glib.h>               // gboolean, GMainLoop, etc.
 #include <libxml/tree.h>        // xmlNode
 
 #include <pacemaker.h>
 #include <pacemaker-internal.h>
 
 #include <crm/crm.h>
 #include <crm/cib.h>
 #include <crm/msg_xml.h>
 #include <crm/common/output_internal.h>
 #include <crm/common/xml.h>
 #include <crm/common/xml_internal.h>
 #include <crm/common/iso8601.h>
 #include <crm/common/ipc_controld.h>
 #include <crm/common/ipc_pacemakerd.h>
 #include <crm/common/mainloop.h>
 
 #define DEFAULT_MESSAGE_TIMEOUT_MS 30000
 
 
 typedef struct {
     pcmk__output_t *out;
     GMainLoop *mainloop;
     int rc;
     guint message_timer_id;
     guint message_timeout_ms;
 } data_t;
 
 static void
 quit_main_loop(data_t *data)
 {
     if (data->mainloop != NULL) {
         GMainLoop *mloop = data->mainloop;
 
         data->mainloop = NULL; // Don't re-enter this block
         pcmk_quit_main_loop(mloop, 10);
         g_main_loop_unref(mloop);
     }
 }
 
 static gboolean
 admin_message_timeout(gpointer user_data)
 {
     data_t *data = user_data;
     pcmk__output_t *out = data->out;
 
     out->err(out, "error: No reply received from controller before timeout (%dms)",
             data->message_timeout_ms);
     data->message_timer_id = 0;
     data->rc = ETIMEDOUT;
     quit_main_loop(data);
     return FALSE; // Tells glib to remove source
 }
 
 static void
 start_main_loop(data_t *data)
 {
     if (data->message_timeout_ms < 1) {
         data->message_timeout_ms = DEFAULT_MESSAGE_TIMEOUT_MS;
     }
 
     data->rc = ECONNRESET; // For unexpected disconnects
     data->mainloop = g_main_loop_new(NULL, FALSE);
     data->message_timer_id = g_timeout_add(data->message_timeout_ms,
                                      admin_message_timeout,
                                      data);
     g_main_loop_run(data->mainloop);
 }
 
 static void
 event_done(data_t *data, pcmk_ipc_api_t *api)
 {
     pcmk_disconnect_ipc(api);
     quit_main_loop(data);
 }
 
 static pcmk_controld_api_reply_t *
 controld_event_reply(data_t *data, pcmk_ipc_api_t *controld_api, enum pcmk_ipc_event event_type, crm_exit_t status, void *event_data)
 {
     pcmk__output_t *out = data->out;
     pcmk_controld_api_reply_t *reply = event_data;
 
     switch (event_type) {
         case pcmk_ipc_event_disconnect:
             if (data->rc == ECONNRESET) { // Unexpected
                 out->err(out, "error: Lost connection to controller");
             }
             event_done(data, controld_api);
             return NULL;
 
         case pcmk_ipc_event_reply:
             break;
 
         default:
             return NULL;
     }
 
     if (data->message_timer_id != 0) {
         g_source_remove(data->message_timer_id);
         data->message_timer_id = 0;
     }
 
     if (status != CRM_EX_OK) {
         out->err(out, "error: Bad reply from controller: %s",
                 crm_exit_str(status));
         data->rc = EBADMSG;
         event_done(data, controld_api);
         return NULL;
     }
 
     if (reply->reply_type != pcmk_controld_reply_ping) {
         out->err(out, "error: Unknown reply type %d from controller",
                 reply->reply_type);
         data->rc = EBADMSG;
         event_done(data, controld_api);
         return NULL;
     }
 
     return reply;
 }
 
 static void
 controller_status_event_cb(pcmk_ipc_api_t *controld_api,
                     enum pcmk_ipc_event event_type, crm_exit_t status,
                     void *event_data, void *user_data)
 {
     data_t *data = user_data;
     pcmk__output_t *out = data->out;
     pcmk_controld_api_reply_t *reply = controld_event_reply(data, controld_api,
         event_type, status, event_data);
 
     if (reply != NULL) {
         out->message(out, "health",
                reply->data.ping.sys_from,
                reply->host_from,
                reply->data.ping.fsa_state,
                reply->data.ping.result);
         data->rc = pcmk_rc_ok;
     }
 
     event_done(data, controld_api);
 }
 
 static void
 designated_controller_event_cb(pcmk_ipc_api_t *controld_api,
                     enum pcmk_ipc_event event_type, crm_exit_t status,
                     void *event_data, void *user_data)
 {
     data_t *data = user_data;
     pcmk__output_t *out = data->out;
     pcmk_controld_api_reply_t *reply = controld_event_reply(data, controld_api,
         event_type, status, event_data);
 
     if (reply != NULL) {
         out->message(out, "dc", reply->host_from);
         data->rc = pcmk_rc_ok;
     }
 
     event_done(data, controld_api);
 }
 
 static void
 pacemakerd_event_cb(pcmk_ipc_api_t *pacemakerd_api,
                     enum pcmk_ipc_event event_type, crm_exit_t status,
                     void *event_data, void *user_data)
 {
     data_t *data = user_data;
     pcmk__output_t *out = data->out;
     pcmk_pacemakerd_api_reply_t *reply = event_data;
 
     crm_time_t *crm_when;
     char *pinged_buf = NULL;
 
     switch (event_type) {
         case pcmk_ipc_event_disconnect:
             if (data->rc == ECONNRESET) { // Unexpected
                 out->err(out, "error: Lost connection to pacemakerd");
             }
             event_done(data, pacemakerd_api);
             return;
 
         case pcmk_ipc_event_reply:
             break;
 
         default:
             return;
     }
 
     if (data->message_timer_id != 0) {
         g_source_remove(data->message_timer_id);
         data->message_timer_id = 0;
     }
 
     if (status != CRM_EX_OK) {
         out->err(out, "error: Bad reply from pacemakerd: %s",
                 crm_exit_str(status));
         event_done(data, pacemakerd_api);
         return;
     }
 
     if (reply->reply_type != pcmk_pacemakerd_reply_ping) {
         out->err(out, "error: Unknown reply type %d from pacemakerd",
                 reply->reply_type);
         event_done(data, pacemakerd_api);
         return;
     }
 
     // Parse desired information from reply
     crm_when = crm_time_new(NULL);
     crm_time_set_timet(crm_when, &reply->data.ping.last_good);
     pinged_buf = crm_time_as_string(crm_when,
         crm_time_log_date | crm_time_log_timeofday |
             crm_time_log_with_timezone);
 
     out->message(out, "pacemakerd-health",
         reply->data.ping.sys_from,
         (reply->data.ping.status == pcmk_rc_ok)?
             pcmk_pacemakerd_api_daemon_state_enum2text(
                 reply->data.ping.state):"query failed",
         (reply->data.ping.status == pcmk_rc_ok)?pinged_buf:"");
     data->rc = pcmk_rc_ok;
     crm_time_free(crm_when);
     free(pinged_buf);
 
     event_done(data, pacemakerd_api);
 }
 
 static pcmk_ipc_api_t *
 ipc_connect(data_t *data, enum pcmk_ipc_server server, pcmk_ipc_callback_t cb)
 {
     int rc;
     pcmk__output_t *out = data->out;
     pcmk_ipc_api_t *api = NULL;
 
 
     rc = pcmk_new_ipc_api(&api, server);
     if (api == NULL) {
         out->err(out, "error: Could not connect to %s: %s",
                 pcmk_ipc_name(api, true),
                 pcmk_rc_str(rc));
         data->rc = rc;
         return NULL;
     }
     if (cb != NULL) {
         pcmk_register_ipc_callback(api, cb, data);
     }
     rc = pcmk_connect_ipc(api, pcmk_ipc_dispatch_main);
     if (rc != pcmk_rc_ok) {
         out->err(out, "error: Could not connect to %s: %s",
                 pcmk_ipc_name(api, true),
                 pcmk_rc_str(rc));
         data->rc = rc;
         return NULL;
     }
 
     return api;
 }
 
 int
 pcmk__controller_status(pcmk__output_t *out, char *dest_node, guint message_timeout_ms)
 {
     data_t data = {
         .out = out,
         .mainloop = NULL,
         .rc = pcmk_rc_ok,
         .message_timer_id = 0,
         .message_timeout_ms = message_timeout_ms
     };
     pcmk_ipc_api_t *controld_api = ipc_connect(&data, pcmk_ipc_controld, controller_status_event_cb);
 
     if (controld_api != NULL) {
         int rc = pcmk_controld_api_ping(controld_api, dest_node);
         if (rc != pcmk_rc_ok) {
             out->err(out, "error: Command failed: %s", pcmk_rc_str(rc));
             data.rc = rc;
         }
 
         start_main_loop(&data);
 
         pcmk_free_ipc_api(controld_api);
     }
 
     return data.rc;
 }
 
 int
 pcmk_controller_status(xmlNodePtr *xml, char *dest_node, unsigned int message_timeout_ms)
 {
     pcmk__output_t *out = NULL;
     int rc = pcmk_rc_ok;
 
     rc = pcmk__out_prologue(&out, xml);
     if (rc != pcmk_rc_ok) {
         return rc;
     }
 
     pcmk__register_lib_messages(out);
 
     rc = pcmk__controller_status(out, dest_node, (guint) message_timeout_ms);
     pcmk__out_epilogue(out, xml, rc);
     return rc;
 }
 
 int
 pcmk__designated_controller(pcmk__output_t *out, guint message_timeout_ms)
 {
     data_t data = {
         .out = out,
         .mainloop = NULL,
         .rc = pcmk_rc_ok,
         .message_timer_id = 0,
         .message_timeout_ms = message_timeout_ms
     };
     pcmk_ipc_api_t *controld_api = ipc_connect(&data, pcmk_ipc_controld, designated_controller_event_cb);
 
     if (controld_api != NULL) {
         int rc = pcmk_controld_api_ping(controld_api, NULL);
         if (rc != pcmk_rc_ok) {
             out->err(out, "error: Command failed: %s", pcmk_rc_str(rc));
             data.rc = rc;
         }
 
         start_main_loop(&data);
 
         pcmk_free_ipc_api(controld_api);
     }
 
     return data.rc;
 }
 
 int
 pcmk_designated_controller(xmlNodePtr *xml, unsigned int message_timeout_ms)
 {
     pcmk__output_t *out = NULL;
     int rc = pcmk_rc_ok;
 
     rc = pcmk__out_prologue(&out, xml);
     if (rc != pcmk_rc_ok) {
         return rc;
     }
 
     pcmk__register_lib_messages(out);
 
     rc = pcmk__designated_controller(out, (guint) message_timeout_ms);
     pcmk__out_epilogue(out, xml, rc);
     return rc;
 }
 
 int
 pcmk__pacemakerd_status(pcmk__output_t *out, char *ipc_name, guint message_timeout_ms)
 {
     data_t data = {
         .out = out,
         .mainloop = NULL,
         .rc = pcmk_rc_ok,
         .message_timer_id = 0,
         .message_timeout_ms = message_timeout_ms
     };
     pcmk_ipc_api_t *pacemakerd_api = ipc_connect(&data, pcmk_ipc_pacemakerd, pacemakerd_event_cb);
 
     if (pacemakerd_api != NULL) {
         int rc = pcmk_pacemakerd_api_ping(pacemakerd_api, ipc_name);
         if (rc != pcmk_rc_ok) {
             out->err(out, "error: Command failed: %s", pcmk_rc_str(rc));
             data.rc = rc;
         }
 
         start_main_loop(&data);
 
         pcmk_free_ipc_api(pacemakerd_api);
     }
 
     return data.rc;
 }
 
 int
 pcmk_pacemakerd_status(xmlNodePtr *xml, char *ipc_name, unsigned int message_timeout_ms)
 {
     pcmk__output_t *out = NULL;
     int rc = pcmk_rc_ok;
 
     rc = pcmk__out_prologue(&out, xml);
     if (rc != pcmk_rc_ok) {
         return rc;
     }
 
     pcmk__register_lib_messages(out);
 
     rc = pcmk__pacemakerd_status(out, ipc_name, (guint) message_timeout_ms);
     pcmk__out_epilogue(out, xml, rc);
     return rc;
 }
 
 /* user data for looping through remote node xpath searches */
 struct node_data {
     pcmk__output_t *out;
     int found;
     const char *field;  /* XML attribute to check for node name */
     const char *type;
     gboolean BASH_EXPORT;
 };
 
 static void
 remote_node_print_helper(xmlNode *result, void *user_data)
 {
     struct node_data *data = user_data;
     pcmk__output_t *out = data->out;
     const char *name = crm_element_value(result, XML_ATTR_UNAME);
     const char *id = crm_element_value(result, data->field);
 
     // node name and node id are the same for remote/guest nodes
     out->message(out, "crmadmin-node", data->type,
                  name ? name : id,
                  id,
                  data->BASH_EXPORT);
     data->found++;
 }
 
 // \return Standard Pacemaker return code
 int
 pcmk__list_nodes(pcmk__output_t *out, char *node_types, gboolean BASH_EXPORT)
 {
     cib_t *the_cib = cib_new();
     xmlNode *xml_node = NULL;
     int rc;
 
     if (the_cib == NULL) {
         return ENOMEM;
     }
     rc = the_cib->cmds->signon(the_cib, crm_system_name, cib_command);
     if (rc != pcmk_ok) {
         return pcmk_legacy2rc(rc);
     }
 
     rc = the_cib->cmds->query(the_cib, NULL, &xml_node,
                               cib_scope_local | cib_sync_call);
     if (rc == pcmk_ok) {
         struct node_data data = {
             .out = out,
             .found = 0,
             .BASH_EXPORT = BASH_EXPORT
         };
 
         out->begin_list(out, NULL, NULL, "nodes");
 
         if (!pcmk__str_empty(node_types) && strstr(node_types, "all")) {
             node_types = NULL;
         }
 
         if (pcmk__str_empty(node_types) || strstr(node_types, "cluster")) {
             data.field = "id";
             data.type = "cluster";
             crm_foreach_xpath_result(xml_node, PCMK__XP_MEMBER_NODE_CONFIG,
                                      remote_node_print_helper, &data);
         }
 
         if (pcmk__str_empty(node_types) || strstr(node_types, "guest")) {
             data.field = "value";
             data.type = "guest";
             crm_foreach_xpath_result(xml_node, PCMK__XP_GUEST_NODE_CONFIG,
                                      remote_node_print_helper, &data);
         }
 
         if (pcmk__str_empty(node_types) || !pcmk__strcmp(node_types, ",|^remote", pcmk__str_regex)) {
             data.field = "id";
             data.type = "remote";
             crm_foreach_xpath_result(xml_node, PCMK__XP_REMOTE_NODE_CONFIG,
                                      remote_node_print_helper, &data);
         }
 
         out->end_list(out);
 
         if (data.found == 0) {
             out->info(out, "No nodes configured");
         }
 
         free_xml(xml_node);
     }
     the_cib->cmds->signoff(the_cib);
     return pcmk_legacy2rc(rc);
 }
 
 int
 pcmk_list_nodes(xmlNodePtr *xml, char *node_types)
 {
     pcmk__output_t *out = NULL;
     int rc = pcmk_rc_ok;
 
     rc = pcmk__out_prologue(&out, xml);
     if (rc != pcmk_rc_ok) {
         return rc;
     }
 
     pcmk__register_lib_messages(out);
 
     rc = pcmk__list_nodes(out, node_types, FALSE);
     pcmk__out_epilogue(out, xml, rc);
     return rc;
 }
diff --git a/lib/services/services_lsb.h b/lib/services/services_lsb.h
index 11a07ca863..df9d8b356a 100644
--- a/lib/services/services_lsb.h
+++ b/lib/services/services_lsb.h
@@ -1,16 +1,18 @@
 /*
- * Copyright 2010-2018 Andrew Beekhof <andrew@beekhof.net>
+ * Copyright 2010-2021 the Pacemaker project contributors
+ *
+ * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef SERVICES_LSB__H
 #  define SERVICES_LSB__H
 
 G_GNUC_INTERNAL int services__get_lsb_metadata(const char *type, char **output);
 G_GNUC_INTERNAL GList *services__list_lsb_agents(void);
 G_GNUC_INTERNAL char *services__lsb_agent_path(const char *agent);
 G_GNUC_INTERNAL bool services__lsb_agent_exists(const char *agent);
 
 #endif
diff --git a/lib/services/services_private.h b/lib/services/services_private.h
index f669ce4925..00aba05f1e 100644
--- a/lib/services/services_private.h
+++ b/lib/services/services_private.h
@@ -1,81 +1,84 @@
 /*
- * Copyright 2010-2018 Red Hat, Inc.
+ * Copyright 2010-2011 Red Hat, Inc.
+ * Later changes copyright 2012-2021 the Pacemaker project contributors
+ *
+ * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef SERVICES_PRIVATE__H
 #  define SERVICES_PRIVATE__H
 
 #  include <glib.h>
 #  include "crm/services.h"
 
 #if SUPPORT_DBUS
 #  include <dbus/dbus.h>
 #endif
 
 #define MAX_ARGC        255
 struct svc_action_private_s {
     char *exec;
     char *args[MAX_ARGC];
 
     uid_t uid;
     gid_t gid;
 
     guint repeat_timer;
     void (*callback) (svc_action_t * op);
     void (*fork_callback) (svc_action_t * op);
 
     int stderr_fd;
     mainloop_io_t *stderr_gsource;
 
     int stdout_fd;
     mainloop_io_t *stdout_gsource;
 
     int stdin_fd;
 #if SUPPORT_DBUS
     DBusPendingCall* pending;
     unsigned timerid;
 #endif
 };
 
 G_GNUC_INTERNAL
 GList *services_os_get_directory_list(const char *root, gboolean files, gboolean executable);
 
 G_GNUC_INTERNAL
 gboolean services_os_action_execute(svc_action_t * op);
 
 G_GNUC_INTERNAL
 GList *resources_os_list_ocf_providers(void);
 
 G_GNUC_INTERNAL
 GList *resources_os_list_ocf_agents(const char *provider);
 
 G_GNUC_INTERNAL
 gboolean services__ocf_agent_exists(const char *provider, const char *agent);
 
 G_GNUC_INTERNAL
 gboolean cancel_recurring_action(svc_action_t * op);
 
 G_GNUC_INTERNAL
 gboolean recurring_action_timer(gpointer data);
 
 G_GNUC_INTERNAL
 gboolean operation_finalize(svc_action_t * op);
 
 G_GNUC_INTERNAL
 void services_add_inflight_op(svc_action_t *op);
 
 G_GNUC_INTERNAL
 void services_untrack_op(svc_action_t *op);
 
 G_GNUC_INTERNAL
 gboolean is_op_blocked(const char *rsc);
 
 #if SUPPORT_DBUS
 G_GNUC_INTERNAL
 void services_set_op_pending(svc_action_t *op, DBusPendingCall *pending);
 #endif
 
 #endif  /* SERVICES_PRIVATE__H */
diff --git a/lib/services/systemd.h b/lib/services/systemd.h
index 23e3479f34..9a46ba70d9 100644
--- a/lib/services/systemd.h
+++ b/lib/services/systemd.h
@@ -1,30 +1,21 @@
-/* 
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+/*
+ * Copyright 2012-2021 the Pacemaker project contributors
  *
- * Copyright (C) 2012 Andrew Beekhof <andrew@beekhof.net>
+ * The version control history for this file may have further details.
+ *
+ * This source code is licensed under the GNU Lesser General Public License
+ * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef SYSTEMD__H
 #  define SYSTEMD__H
 
 #  include <glib.h>
 #  include "crm/services.h"
 
 G_GNUC_INTERNAL GList *systemd_unit_listall(void);
 G_GNUC_INTERNAL gboolean systemd_unit_exec(svc_action_t * op);
 G_GNUC_INTERNAL gboolean systemd_unit_exists(const gchar * name);
 G_GNUC_INTERNAL void systemd_cleanup(void);
 
 #endif  /* SYSTEMD__H */
diff --git a/lib/services/upstart.h b/lib/services/upstart.h
index 7bb9b0d2fa..d44306edd2 100644
--- a/lib/services/upstart.h
+++ b/lib/services/upstart.h
@@ -1,30 +1,22 @@
-/* 
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+/*
+ * Copyright 2010 Senko Rasic <senko.rasic@dobarkod.hr>
+ * Copyright 2010 Ante Karamatic <ivoks@init.hr>
+ * Later changes copyright 2012-2021 the Pacemaker project contributors
  *
- * Copyright (C) 2010 Senko Rasic <senko.rasic@dobarkod.hr>
- * Copyright (c) 2010 Ante Karamatic <ivoks@init.hr>
+ * The version control history for this file may have further details.
+ *
+ * This source code is licensed under the GNU Lesser General Public License
+ * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 #ifndef UPSTART__H
 #  define UPSTART__H
 
 #  include <glib.h>
 #  include "crm/services.h"
 
 G_GNUC_INTERNAL GList *upstart_job_listall(void);
 G_GNUC_INTERNAL gboolean upstart_job_exec(svc_action_t * op);
 G_GNUC_INTERNAL gboolean upstart_job_exists(const gchar * name);
 G_GNUC_INTERNAL void upstart_cleanup(void);
 
 #endif  /* UPSTART__H */
diff --git a/scratch.c b/scratch.c
index a552ab120c..bd0358f5a0 100644
--- a/scratch.c
+++ b/scratch.c
@@ -1,64 +1,53 @@
-/* 
- * Copyright 2004-2013 the Pacemaker project contributors
+/*
+ * Copyright 2004-2021 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
- * 
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- * 
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * This source code is licensed under the GNU General Public License version 2
+ * or later (GPLv2+) WITHOUT ANY WARRANTY.
  */
 
 #include <crm_internal.h>
 
 #include <sys/param.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 
 #include <crm/crm.h>
 #include <crm/cib.h>
 
 #define OPTARGS	"X:"
 
 int
 main(int argc, char **argv)
 {
     int flag;
     xmlNode *top = NULL;
     const char *xml_file = NULL;
 
     crm_log_init(NULL, LOG_TRACE, FALSE, TRUE, argc, argv, FALSE);
     while (1) {
         flag = getopt(argc, argv, OPTARGS);
         if (flag == -1)
             break;
 
         switch (flag) {
             case 'X':
                 xml_file = optarg;
                 break;
             default:
                 printf("Unknown option: -%c\n", flag);
                 break;
         }
     }
 
     top = filename2xml(xml_file);
     free_xml(top);
     return 0;
 }