This is Robin's hacky set of patches for Ganeti

Issue A:
* OpenRC start-stop-daemon no longer supports --oknodo option, which Ganeti
  uses for idempotent stop/start daemons.
* OpenRC treats "--stop --signal 0" as a stop, rather than just doing SIG0.
* Resolve the above by adding using --signal 0 on it's own, and forcing the
  stop/start functions to check before doing things.

Issue B: http/client, rapi/client
* curl is stricter than it used to be!
* Explicitly pass Ganeti's CA cert to Curl when the client is making calls, so
  that it can be trusted.
* Ensure that ONLY the Ganeti CA is used, and not other system certs.

Bonus:
* Extra stuff to make it easier to debug

Open Bugs:
* When using ganeti-vcluster, some tools don't apply the vcluster prefix to the socket path.
  E.g. they try to open /run/ganeti/socket/ganeti-query instead of /var/lib/ganeti-vcluster/node1/run/ganeti/socket/ganeti-query

--- a/lib/bootstrap.py	2021-08-18 22:14:52.728930451 -0700
+++ b/lib/bootstrap.py	2021-08-18 15:29:54.125248452 -0700
@@ -63,7 +63,7 @@
 _INITCONF_ECID = "initconfig-ecid"
 
 #: After how many seconds daemon must be responsive
-_DAEMON_READY_TIMEOUT = 10.0
+_DAEMON_READY_TIMEOUT = 10.0 # Useful to raise during debug
 
 
 def GenerateHmacKey(file_name):
--- a/lib/utils/log.py	2021-08-18 22:14:52.750932142 -0700
+++ b/lib/utils/log.py	2021-08-18 15:51:27.044122859 -0700
@@ -186,9 +186,13 @@
   logging.info("Received request to reopen log files")
 
 
-def SetupLogging(logfile, program, debug=0, stderr_logging=False,
-                 multithreaded=False, syslog=constants.SYSLOG_USAGE,
-                 console_logging=False, root_logger=None):
+def SetupLogging(logfile, program, debug=0, stderr_logging=False,
+                 multithreaded=False, syslog=constants.SYSLOG_USAGE,
+                 console_logging=False, root_logger=None):
+#Useful to use during debug
+#def SetupLogging(logfile, program, debug=10, stderr_logging=True,
+#                 multithreaded=False, syslog=constants.SYSLOG_YES,
+#                 console_logging=True, root_logger=None):
   """Configures the logging module.
 
   @type logfile: str
--- a/lib/rapi/client.py	2021-08-18 22:14:52.667925763 -0700
+++ b/lib/rapi/client.py	2021-08-18 16:56:32.569894199 -0700
@@ -361,6 +361,9 @@
     if cafile or capath or use_curl_cabundle:
       # Require certificates to be checked
       curl.setopt(pycurl.SSL_VERIFYPEER, True)
+      if not use_curl_cabundle:
+        curl.setopt(pycurl.CAINFO, str(''))
+        curl.setopt(pycurl.CAPATH, str(''))
       if cafile:
         curl.setopt(pycurl.CAINFO, str(cafile))
       if capath:
--- a/lib/http/client.py	2021-08-18 22:14:52.470910624 -0700
+++ b/lib/http/client.py	2021-08-18 17:02:50.196376211 -0700
@@ -42,6 +42,7 @@
 from ganeti import compat
 from ganeti import netutils
 from ganeti import locking
+from ganeti import pathutils
 
 
 class HttpClientRequest(object):
@@ -141,7 +142,9 @@
   @param req: HTTP request
 
   """
+  noded_cert = pathutils.NODED_CERT_FILE
   logging.debug("Starting request %r", req)
+  #logging.debug("request2 %s", req.url)
 
   url = req.url
   method = req.method
@@ -152,8 +155,13 @@
   resp_buffer = BytesIO()
 
   # Configure client for request
-  curl.setopt(pycurl.VERBOSE, False)
+  curl.setopt(pycurl.VERBOSE, False)
+  #curl.setopt(pycurl.VERBOSE, True)
   curl.setopt(pycurl.NOSIGNAL, True)
+  #curl.setopt(pycurl.SSL_VERIFYPEER, False)
+  #curl.setopt(pycurl.SSL_VERIFYHOST, 0)
+  curl.setopt(pycurl.CAINFO, noded_cert)
+  curl.setopt(pycurl.CAPATH, noded_cert)
   curl.setopt(pycurl.USERAGENT, http.HTTP_GANETI_VERSION)
   curl.setopt(pycurl.PROXY, "")
   curl.setopt(pycurl.CUSTOMREQUEST, method)

--- a/daemons/daemon-util.in	2021-08-18 22:14:52.442908473 -0700
+++ b/daemons/daemon-util.in	2021-08-18 20:00:53.111847248 -0700
@@ -260,6 +260,8 @@
     echo 'Missing daemon name.' >&2
     return 1
   fi
+  #echo "DEBUG: $0: check $1" 1>&2
+  #set -x
 
   local name="$1"; shift
   local pidfile=$(_daemon_pidfile $name)
@@ -273,21 +275,24 @@
       return 1
     fi
   elif type -p start-stop-daemon >/dev/null; then
-    start-stop-daemon --stop --signal 0 --quiet \
+    start-stop-daemon --test --signal 0 --quiet \
       --pidfile $pidfile --name "$name"
+    return $?
   else
     _ignore_error status \
       -p $pidfile \
       $daemonexec
+    return $?
   fi
 }
 
 # Starts a daemon
-start() {
+_start() {
   if [[ "$#" -lt 1 ]]; then
     echo 'Missing daemon name.' >&2
     return 1
   fi
+  #echo "DEBUG: $0: _start $1" 1>&2
 
   local name="$1"; shift
   # Convert daemon name to uppercase after removing "ganeti-" prefix
@@ -342,11 +347,12 @@
 }
 
 # Stops a daemon
-stop() {
+_stop() {
   if [[ "$#" -lt 1 ]]; then
     echo 'Missing daemon name.' >&2
     return 1
   fi
+  #echo "DEBUG: $0: stop $1" 1>&2
 
   local name="$1"; shift
   local pidfile=$(_daemon_pidfile $name)
@@ -371,10 +377,32 @@
       return 1
     fi
 
-    start $name
+    _start $name
+  fi
+}
+
+# Stop a daemon only if running
+check_and_stop() {
+  local name="$1"
+
+  if check $name; then
+    if use_systemctl; then
+      echo "${name} supervised by systemd but not running, will not restart."
+      return 1
+    fi
+
+    _stop $name
   fi
 }
 
+stop() {
+    check_and_stop "$@"
+}
+
+start() {
+    check_and_start "$@"
+}
+
 # Starts the master role
 start_master() {
   if use_systemctl; then
@@ -423,7 +451,7 @@
     systemctl stop ganeti.target
   else
     for i in $(list_stop_daemons); do
-      stop $i
+      stop $i
     done
   fi
 }
