Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package fence-agents for openSUSE:Factory 
checked in at 2024-11-26 20:56:26
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/fence-agents (Old)
 and      /work/SRC/openSUSE:Factory/.fence-agents.new.28523 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "fence-agents"

Tue Nov 26 20:56:26 2024 rev:79 rq:1226483 
version:4.15.0+git.1731052905.05fd299e

Changes:
--------
--- /work/SRC/openSUSE:Factory/fence-agents/fence-agents.changes        
2024-09-20 17:13:23.063162148 +0200
+++ /work/SRC/openSUSE:Factory/.fence-agents.new.28523/fence-agents.changes     
2024-11-26 20:57:44.255016655 +0100
@@ -1,0 +2,11 @@
+Tue Nov 19 10:48:42 UTC 2024 - vark...@suse.com
+
+- Update to version 4.15.0+git.1731052905.05fd299e:
+  * fence_nutanix_ahv: Add fence agent support for Nutanix AHV Cluster (#600)
+  * fencing: fix "?" typo in required field for the login parameter
+  * fence_ibm_powervs: add private endpoint and token file support (#597)
+  * fence_mpath: fix 0x-format patch causing unfencing issue, and use 
re.MULTILINE to avoid duplicating device dev/key lines in 
/run/cluster/mpath.devices
+  * fence_bladecenter/fence_raritan_px3: use r"" on regex string to avoid 
SyntaxWarning
+  * fence_scsi: preempt clears all devices on the mpath device, so only run it 
for the first device
+
+-------------------------------------------------------------------

Old:
----
  fence-agents-4.15.0+git.1724675137.ca9ae93a.tar.xz

New:
----
  fence-agents-4.15.0+git.1731052905.05fd299e.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ fence-agents.spec ++++++
--- /var/tmp/diff_new_pack.eoENkc/_old  2024-11-26 20:57:45.011048062 +0100
+++ /var/tmp/diff_new_pack.eoENkc/_new  2024-11-26 20:57:45.011048062 +0100
@@ -19,7 +19,7 @@
 %define agent_list aliyun alom apc apc_snmp aws azure_arm bladecenter brocade 
cisco_mds cisco_ucs compute docker drac5 dummy eaton_snmp eaton_ssh emerson eps 
evacuate gce hds_cb hpblade ibmblade ibmz ibm_powervs ibm_vpc ifmib ilo 
ilo_moonshot ilo_mp ilo_ssh intelmodular ipdu ipmilan ironic kdump ldom lpar 
mpath netio openstack powerman pve raritan rcd_serial redfish rhevm rsa rsb 
sanbox2 sbd scsi vbox virsh vmware vmware_rest wti xenapi zvm
 Name:           fence-agents
 Summary:        Set of unified programs capable of host isolation ("fencing")
-Version:        4.15.0+git.1724675137.ca9ae93a
+Version:        4.15.0+git.1731052905.05fd299e
 Release:        0
 License:        GPL-2.0-or-later AND LGPL-2.0-or-later
 Group:          Productivity/Clustering/HA

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.eoENkc/_old  2024-11-26 20:57:45.051049723 +0100
+++ /var/tmp/diff_new_pack.eoENkc/_new  2024-11-26 20:57:45.055049889 +0100
@@ -3,6 +3,6 @@
             <param 
name="url">git://github.com/ClusterLabs/fence-agents.git</param>
           <param 
name="changesrevision">8d746be92f191aa289f13a3703031c122a5e6cf3</param></service><service
 name="tar_scm">
                 <param 
name="url">https://github.com/ClusterLabs/fence-agents</param>
-              <param 
name="changesrevision">ca9ae93a90e28876a010e7a065f62a387b857ad2</param></service></servicedata>
+              <param 
name="changesrevision">05fd299e094c6981b4c5b943dee03a29e78ee016</param></service></servicedata>
 (No newline at EOF)
 

++++++ fence-agents-4.15.0+git.1724675137.ca9ae93a.tar.xz -> 
fence-agents-4.15.0+git.1731052905.05fd299e.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fence-agents-4.15.0+git.1724675137.ca9ae93a/agents/bladecenter/fence_bladecenter.py
 
new/fence-agents-4.15.0+git.1731052905.05fd299e/agents/bladecenter/fence_bladecenter.py
--- 
old/fence-agents-4.15.0+git.1724675137.ca9ae93a/agents/bladecenter/fence_bladecenter.py
     2024-08-26 14:25:37.000000000 +0200
+++ 
new/fence-agents-4.15.0+git.1731052905.05fd299e/agents/bladecenter/fence_bladecenter.py
     2024-11-08 09:01:45.000000000 +0100
@@ -96,7 +96,7 @@
        ##
        ## Operate the fencing device
        ######
-       conn = fence_login(options, "(username\s*:\s*)")
+       conn = fence_login(options, r"(username\s*:\s*)")
        result = fence_action(conn, options, set_power_status, 
get_power_status, get_blades_list)
        fence_logout(conn, "exit")
        sys.exit(result)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fence-agents-4.15.0+git.1724675137.ca9ae93a/agents/ibm_powervs/fence_ibm_powervs.py
 
new/fence-agents-4.15.0+git.1731052905.05fd299e/agents/ibm_powervs/fence_ibm_powervs.py
--- 
old/fence-agents-4.15.0+git.1724675137.ca9ae93a/agents/ibm_powervs/fence_ibm_powervs.py
     2024-08-26 14:25:37.000000000 +0200
+++ 
new/fence-agents-4.15.0+git.1731052905.05fd299e/agents/ibm_powervs/fence_ibm_powervs.py
     2024-11-08 09:01:45.000000000 +0100
@@ -1,13 +1,14 @@
 #!@PYTHON@ -tt
 
 import sys
-import pycurl, io, json
+import pycurl
+import io
+import json
 import logging
 import atexit
-import time
+
 sys.path.append("@FENCEAGENTSLIBDIR@")
-from fencing import *
-from fencing import fail, run_delay, EC_LOGIN_DENIED, EC_STATUS
+from fencing import all_opt, atexit_handler, check_input, process_input, 
show_docs, fence_action, fail, run_delay, EC_STATUS
 
 state = {
         "ACTIVE": "on",
@@ -18,15 +19,35 @@
 }
 
 def get_token(conn, options):
-        try:
-                command = "identity/token"
-                action = 
"grant_type=urn%3Aibm%3Aparams%3Aoauth%3Agrant-type%3Aapikey&apikey={}".format(options["--token"])
-                res = send_command(conn, command, "POST", action, 
printResult=False)
-        except Exception as e:
-                logging.debug("Failed: {}".format(e))
-                return "TOKEN_IS_MISSING_OR_WRONG"
-
-        return res["access_token"]
+       try:
+               if options["--token"][0] == '@':
+                       key_file = options["--token"][1:]
+                       try:
+                               # read the API key from a file
+                               with open(key_file, "r") as f:
+                                       try:
+                                               keys = json.loads(f.read())
+                                               # data seems to be in json 
format
+                                               # return the value of the item 
with the key 'Apikey'
+                                               api_key = keys.get("Apikey", "")
+                                               if not api_key:
+                                                       # backward 
compatibility: former key name was 'apikey'
+                                                       api_key = 
keys.get("apikey", "")
+                                       # data is text, return as is
+                                       except ValueError:
+                                               api_key = f.read().strip()
+                       except FileNotFoundError:
+                               logging.debug("Failed: Cannot open file 
{}".format(key_file))
+                               return "TOKEN_IS_MISSING_OR_WRONG"
+               else:
+                       api_key = options["--token"]
+               command = "identity/token"
+               action = 
"grant_type=urn%3Aibm%3Aparams%3Aoauth%3Agrant-type%3Aapikey&apikey={}".format(api_key)
+               res = send_command(conn, command, "POST", action, 
printResult=False)
+       except Exception as e:
+               logging.debug("Failed: {}".format(e))
+               return "TOKEN_IS_MISSING_OR_WRONG"
+       return res["access_token"]
 
 def get_list(conn, options):
        outlets = {}
@@ -41,7 +62,7 @@
        for r in res["pvmInstances"]:
                if options["--verbose-level"] > 1:
                        logging.debug(json.dumps(r, indent=2))
-               outlets[r["pvmInstanceID"]] = (r["serverName"], 
state[r["status"]])
+               outlets[r["pvmInstanceID"]] = (r["serverName"], 
state.get(r["status"], "unknown"))
 
        return outlets
 
@@ -97,7 +118,7 @@
                else:
                        logging.debug("Failed: Unable to cycle with {} for 
{}".format(options["--action"], e))
                        fail(EC_STATUS)
-       return True 
+       return True
 
 def connect(opt, token):
        conn = pycurl.Curl()
@@ -130,7 +151,10 @@
        conn = pycurl.Curl()
 
        # setup correct URL
-       conn.base_url = "https://iam.cloud.ibm.com/";
+       if opt["--api-type"] == "private":
+               conn.base_url = "https://private.iam.cloud.ibm.com/";
+       else:
+               conn.base_url = "https://iam.cloud.ibm.com/";
 
        if opt["--verbose-level"] > 1:
                conn.setopt(pycurl.VERBOSE, 1)
@@ -265,9 +289,9 @@
        define_new_opts()
 
        all_opt["shell_timeout"]["default"] = "500"
-       all_opt["power_timeout"]["default"] = "30"
-       all_opt["power_wait"]["default"] = "1"
-       all_opt["stonith_status_sleep"]["default"] = "2"
+       all_opt["power_timeout"]["default"] = "120"
+       all_opt["power_wait"]["default"] = "15"
+       all_opt["stonith_status_sleep"]["default"] = "10"
        all_opt["api-type"]["default"] = "private"
        all_opt["proxy"]["default"] = ""
 
@@ -275,8 +299,8 @@
 
        docs = {}
        docs["shortdesc"] = "Fence agent for IBM PowerVS"
-       docs["longdesc"] = """fence_ibm_powervs is a Power Fencing agent which 
can be \
-used with IBM PowerVS to fence virtual machines."""
+       docs["longdesc"] = """fence_ibm_powervs is a power fencing agent for \
+IBM Power Virtual Server (IBM PowerVS) to fence virtual server instances."""
        docs["vendorurl"] = "https://www.ibm.com";
        show_docs(options, docs)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fence-agents-4.15.0+git.1724675137.ca9ae93a/agents/mpath/fence_mpath.py 
new/fence-agents-4.15.0+git.1731052905.05fd299e/agents/mpath/fence_mpath.py
--- old/fence-agents-4.15.0+git.1724675137.ca9ae93a/agents/mpath/fence_mpath.py 
2024-08-26 14:25:37.000000000 +0200
+++ new/fence-agents-4.15.0+git.1731052905.05fd299e/agents/mpath/fence_mpath.py 
2024-11-08 09:01:45.000000000 +0100
@@ -40,7 +40,7 @@
                        if options["--plug"] not in 
get_registration_keys(options, dev):
                                count += 1
                                logging.debug("Failed to register key "\
-                                       + options["--plug"] + "on device " + 
dev + "\n")
+                                       + options["--plug"] + " on device " + 
dev + "\n")
                                continue
                        dev_write(options, dev)
 
@@ -147,8 +147,9 @@
                store_fh = open(file_path, "a+")
        except IOError:
                fail_usage("Failed: Cannot open file \""+ file_path + "\"")
+       store_fh.seek(0)
        out = store_fh.read()
-       if not re.search(r"^" + dev + r"\s+", out):
+       if not re.search(r"^{}\s+{}$".format(dev, options["--plug"]), out, 
flags=re.MULTILINE):
                store_fh.write(dev + "\t" + options["--plug"] + "\n")
        store_fh.close()
 
@@ -332,7 +333,7 @@
                fail_usage("Failed: No devices found")
 
        options["devices"] = [d for d in re.split(r"\s*,\s*|\s+", 
options["--devices"].strip()) if d]
-       options["--plug"] = re.sub(r"^0x0*|^0+", "", options["--plug"])
+       options["--plug"] = re.sub(r"^0x0*|^0+", "", options.get("--plug", ""))
        # Input control END
 
        result = fence_action(None, options, set_status, get_status)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fence-agents-4.15.0+git.1724675137.ca9ae93a/agents/nutanix_ahv/fence_nutanix_ahv.py
 
new/fence-agents-4.15.0+git.1731052905.05fd299e/agents/nutanix_ahv/fence_nutanix_ahv.py
--- 
old/fence-agents-4.15.0+git.1724675137.ca9ae93a/agents/nutanix_ahv/fence_nutanix_ahv.py
     1970-01-01 01:00:00.000000000 +0100
+++ 
new/fence-agents-4.15.0+git.1731052905.05fd299e/agents/nutanix_ahv/fence_nutanix_ahv.py
     2024-11-08 09:01:45.000000000 +0100
@@ -0,0 +1,574 @@
+#!@PYTHON@ -tt
+
+# AHV Fence agent
+# Compatible with Nutanix v4 API
+
+
+import atexit
+import logging
+import sys
+import time
+import uuid
+import requests
+
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, EC_LOGIN_DENIED, EC_GENERIC_ERROR, EC_TIMED_OUT, 
run_delay, EC_BAD_ARGS
+
+
+V4_VERSION = '4.0'
+MIN_TIMEOUT = 60
+PC_PORT = 9440
+POWER_STATES = {"ON": "on", "OFF": "off", "PAUSED": "off", "UNKNOWN": 
"unknown"}
+
+
+class NutanixClientException(Exception):
+    pass
+
+
+class AHVFenceAgentException(Exception):
+    pass
+
+
+class TaskTimedOutException(Exception):
+    pass
+
+
+class InvalidArgsException(Exception):
+    pass
+
+
+class NutanixClient:
+    def __init__(self, username, password, disable_warnings=False):
+        self.username = username
+        self.password = password
+        self.valid_status_codes = [200, 202]
+        self.disable_warnings = disable_warnings
+
+    def request(self, url, method='GET', headers=None, **kwargs):
+        session = requests.Session()
+        session.auth = (self.username, self.password)
+
+        if self.disable_warnings:
+            requests.packages.urllib3.disable_warnings()
+
+        if headers:
+            session.headers.update(headers)
+
+        response = None
+
+        try:
+            logging.debug("Sending %s request to %s", method, url)
+            response = session.request(method, url, **kwargs)
+            response.raise_for_status()
+        except requests.exceptions.SSLError as err:
+            logging.error("Secure connection failed, verify SSL certificate")
+            logging.error("Error message: %s", err)
+            raise NutanixClientException("Secure connection failed") from err
+        except requests.exceptions.RequestException as err:
+            logging.error("API call failed: %s", response.text)
+            logging.error("Error message: %s", err)
+            raise NutanixClientException(f"API call failed: {err}") from err
+        except Exception as err:
+            logging.error("API call failed: %s", response.text)
+            logging.error("Unknown error %s", err)
+            raise NutanixClientException(f"API call failed: {err}") from err
+
+        if response.status_code not in self.valid_status_codes:
+            logging.error("API call returned status code %s", 
response.status_code)
+            raise NutanixClientException(f"API call failed: {response}")
+
+        return response
+
+
+class NutanixV4Client(NutanixClient):
+    def __init__(self, host=None, username=None, password=None,
+                 verify=True, disable_warnings=False):
+        self.host = host
+        self.username = username
+        self.password = password
+        self.verify = verify
+        self.base_url = f"https://{self.host}:{PC_PORT}/api";
+        self.vm_url = f"{self.base_url}/vmm/v{V4_VERSION}/ahv/config/vms"
+        self.task_url = f"{self.base_url}/prism/v{V4_VERSION}/config/tasks"
+        super().__init__(username, password, disable_warnings)
+
+    def _get_headers(self, vm_uuid=None):
+        resp = None
+        headers = {'Accept':'application/json',
+                   'Content-Type': 'application/json'}
+
+        if vm_uuid:
+            try:
+                resp = self._get_vm(vm_uuid)
+            except AHVFenceAgentException as err:
+                logging.error("Unable to retrieve etag")
+                raise AHVFenceAgentException from err
+
+            etag_str = resp.headers['Etag']
+            request_id = str(uuid.uuid1())
+            headers['If-Match'] = etag_str
+            headers['Ntnx-Request-Id'] = request_id
+
+        return headers
+
+    def _get_all_vms(self, filter_str=None, limit=None):
+        vm_url = self.vm_url
+
+        if filter_str and limit:
+            vm_url = f"{vm_url}?$filter={filter_str}&$limit={limit}"
+        elif filter_str and not limit:
+            vm_url = f"{vm_url}?$filter={filter_str}"
+        elif limit and not filter_str:
+            vm_url = f"{vm_url}?$limit={limit}"
+
+        logging.debug("Getting info for all VMs, %s", vm_url)
+        header_str = self._get_headers()
+
+        try:
+            resp = self.request(url=vm_url, method='GET',
+                                headers=header_str, verify=self.verify)
+        except NutanixClientException as err:
+            logging.error("Unable to retrieve VM info")
+            raise AHVFenceAgentException from err
+
+        vms = resp.json()
+        return vms
+
+    def _get_vm_uuid(self, vm_name):
+        vm_uuid = None
+        resp = None
+
+        if not vm_name:
+            logging.error("VM name was not provided")
+            raise AHVFenceAgentException("VM name not provided")
+
+        try:
+            filter_str = f"name eq '{vm_name}'"
+            resp = self._get_all_vms(filter_str=filter_str)
+        except AHVFenceAgentException as err:
+            logging.error("Failed to get VM info for VM %s", vm_name)
+            raise AHVFenceAgentException from err
+
+        if not resp or not isinstance(resp, dict):
+            logging.error("Failed to retrieve VM UUID for VM %s", vm_name)
+            raise AHVFenceAgentException(f"Failed to get VM UUID for 
{vm_name}")
+
+        if 'data' not in resp:
+            err = f"Error: Unsuccessful match for VM name: {vm_name}"
+            logging.error("Failed to retrieve VM UUID for VM %s", vm_name)
+            raise AHVFenceAgentException(err)
+
+        for vm in resp['data']:
+            if vm['name'] == vm_name:
+                vm_uuid = vm['extId']
+                break
+
+        return vm_uuid
+
+    def _get_vm(self, vm_uuid):
+        if not vm_uuid:
+            logging.error("VM UUID was not provided")
+            raise AHVFenceAgentException("VM UUID not provided")
+
+        vm_url = self.vm_url + f"/{vm_uuid}"
+        logging.debug("Getting config information for VM, %s", vm_uuid)
+
+        try:
+            header_str = self._get_headers()
+            resp = self.request(url=vm_url, method='GET',
+                                headers=header_str, verify=self.verify)
+        except NutanixClientException as err:
+            logging.error("Failed to retrieve VM details "
+                          "for VM UUID: %s", vm_uuid)
+            raise AHVFenceAgentException from err
+        except AHVFenceAgentException as err:
+            logging.error("Failed to retrieve etag from headers")
+            raise AHVFenceAgentException from err
+
+        return resp
+
+    def _power_on_off_vm(self, power_state=None, vm_uuid=None):
+        resp = None
+        vm_url = None
+
+        if not vm_uuid:
+            logging.error("VM UUID was not provided")
+            raise AHVFenceAgentException("VM UUID not provided")
+        if not power_state:
+            logging.error("Requested VM power state is None")
+            raise InvalidArgsException
+
+        power_state = power_state.lower()
+
+        if power_state == 'on':
+            vm_url = self.vm_url + f"/{vm_uuid}/$actions/power-on"
+            logging.debug("Sending request to power on VM, %s", vm_uuid)
+        elif power_state == 'off':
+            vm_url = self.vm_url + f"/{vm_uuid}/$actions/power-off"
+            logging.debug("Sending request to power off VM, %s", vm_uuid)
+        else:
+            logging.error("Invalid power state specified: %s", power_state)
+            raise InvalidArgsException
+
+        try:
+            headers_str = self._get_headers(vm_uuid)
+            resp = self.request(url=vm_url, method='POST',
+                                headers=headers_str, verify=self.verify)
+        except NutanixClientException as err:
+            logging.error("Failed to power off VM %s", vm_uuid)
+            raise AHVFenceAgentException from err
+        except AHVFenceAgentException as err:
+            logging.error("Failed to retrieve etag from headers")
+            raise AHVFenceAgentException from err
+
+        return resp
+
+    def _power_cycle_vm(self, vm_uuid):
+        if not vm_uuid:
+            logging.error("VM UUID was not provided")
+            raise AHVFenceAgentException("VM UUID not provided")
+
+        resp = None
+        vm_url = self.vm_url + f"/{vm_uuid}/$actions/power-cycle"
+        logging.debug("Sending request to power cycle VM, %s", vm_uuid)
+
+        try:
+            header_str = self._get_headers(vm_uuid)
+            resp = self.request(url=vm_url, method='POST',
+                                headers=header_str, verify=self.verify)
+        except NutanixClientException as err:
+            logging.error("Failed to power on VM %s", vm_uuid)
+            raise AHVFenceAgentException from err
+        except AHVFenceAgentException as err:
+            logging.error("Failed to retrieve etag from headers")
+            raise AHVFenceAgentException from err
+
+        return resp
+
+    def _wait_for_task(self, task_uuid, timeout=None):
+        if not task_uuid:
+            logging.error("Task UUID was not provided")
+            raise AHVFenceAgentException("Task UUID not provided")
+
+        task_url = f"{self.task_url}/{task_uuid}"
+        header_str = self._get_headers()
+        task_resp = None
+        interval = 5
+        task_status = None
+
+        if not timeout:
+            timeout = MIN_TIMEOUT
+        else:
+            try:
+                timeout = int(timeout)
+            except ValueError:
+                timeout = MIN_TIMEOUT
+
+        while task_status != 'SUCCEEDED':
+            if timeout <= 0:
+                raise TaskTimedOutException(f"Task timed out: {task_uuid}")
+
+            time.sleep(interval)
+            timeout = timeout - interval
+
+            try:
+                task_resp = self.request(url=task_url, method='GET',
+                                         headers=header_str, 
verify=self.verify)
+                task_status = task_resp.json()['data']['status']
+            except NutanixClientException as err:
+                logging.error("Unable to retrieve task status")
+                raise AHVFenceAgentException from err
+            except Exception as err:
+                logging.error("Unknown error")
+                raise AHVFenceAgentException from err
+
+            if task_status == 'FAILED':
+                raise AHVFenceAgentException(f"Task failed, task uuid: 
{task_uuid}")
+
+    def list_vms(self, filter_str=None, limit=None):
+        vms = None
+        vm_list = {}
+
+        try:
+            vms = self._get_all_vms(filter_str, limit)
+        except NutanixClientException as err:
+            logging.error("Failed to retrieve VM list")
+            raise AHVFenceAgentException from err
+
+        if not vms or not isinstance(vms, dict):
+            logging.error("Failed to retrieve VM list")
+            raise AHVFenceAgentException("Unable to get VM list")
+
+        if 'data' not in vms:
+            err = "Got invalid or empty VM list"
+            logging.debug(err)
+        else:
+            for vm in vms['data']:
+                vm_name = vm['name']
+                ext_id = vm['extId']
+                power_state = vm['powerState']
+                vm_list[vm_name] = (ext_id, power_state)
+
+        return vm_list
+
+    def get_power_state(self, vm_name=None, vm_uuid=None):
+        resp = None
+        power_state = None
+
+        if not vm_name and not vm_uuid:
+            logging.error("Require at least one of VM name or VM UUID")
+            raise InvalidArgsException("No arguments provided")
+
+        if not vm_uuid:
+            try:
+                vm_uuid = self._get_vm_uuid(vm_name)
+            except AHVFenceAgentException as err:
+                logging.error("Unable to retrieve UUID of VM, %s", vm_name)
+                raise AHVFenceAgentException from err
+
+        try:
+            resp = self._get_vm(vm_uuid)
+        except AHVFenceAgentException as err:
+            logging.error("Unable to retrieve power state of VM %s", vm_uuid)
+            raise AHVFenceAgentException from err
+
+        try:
+            power_state = resp.json()['data']['powerState']
+        except AHVFenceAgentException as err:
+            logging.error("Failed to retrieve power state of VM %s", vm_uuid)
+            raise AHVFenceAgentException from err
+
+        return POWER_STATES[power_state]
+
+    def set_power_state(self, vm_name=None, vm_uuid=None,
+                        power_state='off', timeout=None):
+        resp = None
+        current_power_state = None
+        power_state = power_state.lower()
+
+        if not timeout:
+            timeout = MIN_TIMEOUT
+
+        if not vm_name and not vm_uuid:
+            logging.error("Require at least one of VM name or VM UUID")
+            raise InvalidArgsException("No arguments provided")
+
+        if not vm_uuid:
+            vm_uuid = self._get_vm_uuid(vm_name)
+
+        try:
+            current_power_state = self.get_power_state(vm_uuid=vm_uuid)
+        except AHVFenceAgentException as err:
+            raise AHVFenceAgentException from err
+
+        if current_power_state.lower() == power_state.lower():
+            logging.debug("VM already powered %s", power_state.lower())
+            return
+
+        if power_state.lower() == 'on':
+            resp = self._power_on_off_vm(power_state, vm_uuid)
+        elif power_state.lower() == 'off':
+            resp = self._power_on_off_vm(power_state, vm_uuid)
+
+        task_id = resp.json()['data']['extId']
+
+        try:
+            self._wait_for_task(task_id, timeout)
+        except AHVFenceAgentException as err:
+            logging.error("Failed to power %s VM", power_state.lower())
+            logging.error("VM power %s task failed", power_state.lower())
+            raise AHVFenceAgentException from err
+        except TaskTimedOutException as err:
+            logging.error("Timed out powering %s VM %s",
+                          power_state.lower(), vm_uuid)
+            raise TaskTimedOutException from err
+
+        logging.debug("Powered %s VM, %s successfully",
+                     power_state.lower(), vm_uuid)
+
+    def power_cycle_vm(self, vm_name=None, vm_uuid=None, timeout=None):
+        resp = None
+        status = None
+
+        if not timeout:
+            timeout = MIN_TIMEOUT
+
+        if not vm_name and not vm_uuid:
+            logging.error("Require at least one of VM name or VM UUID")
+            raise InvalidArgsException("No arguments provided")
+
+        if not vm_uuid:
+            vm_uuid = self._get_vm_uuid(vm_name)
+
+        resp = self._power_cycle_vm(vm_uuid)
+        task_id = resp.json()['data']['extId']
+
+        try:
+            self._wait_for_task(task_id, timeout)
+        except AHVFenceAgentException as err:
+            logging.error("Failed to power-cycle VM %s", vm_uuid)
+            logging.error("VM power-cycle task failed with status, %s", status)
+            raise AHVFenceAgentException from err
+        except TaskTimedOutException as err:
+            logging.error("Timed out power-cycling VM %s", vm_uuid)
+            raise TaskTimedOutException from err
+
+
+        logging.debug("Power-cycled VM, %s", vm_uuid)
+
+
+def connect(options):
+    host = options["--ip"]
+    username = options["--username"]
+    password = options["--password"]
+    verify_ssl = True
+    disable_warnings = False
+
+    if "--ssl-insecure" in options:
+        verify_ssl = False
+        disable_warnings = True
+
+    client = NutanixV4Client(host, username, password,
+                             verify_ssl, disable_warnings)
+
+    try:
+        client.list_vms(limit=1)
+    except AHVFenceAgentException as err:
+        logging.error("Connection to Prism Central Failed")
+        logging.error(err)
+        fail(EC_LOGIN_DENIED)
+
+    return client
+
+def get_list(client, options):
+    vm_list = None
+
+    filter_str = options.get("--filter", None)
+    limit = options.get("--limit", None)
+
+    try:
+        vm_list = client.list_vms(filter_str, limit)
+    except AHVFenceAgentException as err:
+        logging.error("Failed to list VMs")
+        logging.error(err)
+        fail(EC_GENERIC_ERROR)
+
+    return vm_list
+
+def get_power_status(client, options):
+    vmid = None
+    name = None
+    power_state = None
+
+    vmid = options.get("--uuid", None)
+    name = options.get("--plug", None)
+
+    if not vmid and not name:
+        logging.error("Need VM name or VM UUID for power op")
+        fail(EC_BAD_ARGS)
+    try:
+        power_state = client.get_power_state(vm_name=name, vm_uuid=vmid)
+    except AHVFenceAgentException:
+        fail(EC_GENERIC_ERROR)
+    except InvalidArgsException:
+        fail(EC_BAD_ARGS)
+
+    return power_state
+
+def set_power_status(client, options):
+    action = options["--action"].lower()
+    timeout = options.get("--power-timeout", None)
+    vmid = options.get("--uuid", None)
+    name = options.get("--plug", None)
+
+    if not name and not vmid:
+        logging.error("Need VM name or VM UUID to set power state of a VM")
+        fail(EC_BAD_ARGS)
+
+    try:
+        client.set_power_state(vm_name=name, vm_uuid=vmid,
+                               power_state=action, timeout=timeout)
+    except AHVFenceAgentException as err:
+        logging.error(err)
+        fail(EC_GENERIC_ERROR)
+    except TaskTimedOutException as err:
+        logging.error(err)
+        fail(EC_TIMED_OUT)
+    except InvalidArgsException:
+        fail(EC_BAD_ARGS)
+
+def power_cycle(client, options):
+    timeout = options.get("--power-timeout", None)
+    vmid = options.get("--uuid", None)
+    name = options.get("--plug", None)
+
+    if not name and not vmid:
+        logging.error("Need VM name or VM UUID to set power cycling a VM")
+        fail(EC_BAD_ARGS)
+
+    try:
+        client.power_cycle_vm(vm_name=name, vm_uuid=vmid, timeout=timeout)
+    except AHVFenceAgentException as err:
+        logging.error(err)
+        fail(EC_GENERIC_ERROR)
+    except TaskTimedOutException as err:
+        logging.error(err)
+        fail(EC_TIMED_OUT)
+    except InvalidArgsException:
+        fail(EC_BAD_ARGS)
+
+def define_new_opts():
+    all_opt["filter"] = {
+            "getopt": ":",
+            "longopt": "filter",
+            "help": """
+            --filter=[filter]  Filter list, list VMs actions.
+            --filter=\"name eq 'node1-vm'\"
+            --filter=\"startswith(name,'node')\"
+            --filter=\"name in ('node1-vm','node-3-vm')\" """,
+            "required": "0",
+            "shortdesc": "Filter list, get_list"
+            "e.g: \"name eq 'node1-vm'\"",
+            "order": 2
+            }
+
+def main():
+    device_opt = [
+            "ipaddr",
+            "login",
+            "passwd",
+            "ssl",
+            "notls",
+            "web",
+            "port",
+            "filter",
+            "method",
+            "disable_timeout",
+            "power_timeout"
+            ]
+
+    atexit.register(atexit_handler)
+    define_new_opts()
+
+    all_opt["power_timeout"]["default"] = str(MIN_TIMEOUT)
+    options = check_input(device_opt, process_input(device_opt))
+    docs = {}
+    docs["shortdesc"] = "Fencing agent for Nutanix AHV Cluster VMs."
+    docs["longdesc"] = """fence_ahv is a power fencing agent for \
+virtual machines deployed on Nutanix AHV cluster with the AHV cluster \
+being managed by Prism Central."""
+    docs["vendorurl"] = "https://www.nutanix.com";
+    show_docs(options, docs)
+    run_delay(options)
+    client = connect(options)
+
+    result = fence_action(client, options, set_power_status, get_power_status,
+                          get_list, reboot_cycle_fn=power_cycle
+                         )
+
+    sys.exit(result)
+
+
+if __name__ == "__main__":
+    main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fence-agents-4.15.0+git.1724675137.ca9ae93a/agents/raritan_px3/fence_raritan_px3.py
 
new/fence-agents-4.15.0+git.1731052905.05fd299e/agents/raritan_px3/fence_raritan_px3.py
--- 
old/fence-agents-4.15.0+git.1724675137.ca9ae93a/agents/raritan_px3/fence_raritan_px3.py
     2024-08-26 14:25:37.000000000 +0200
+++ 
new/fence-agents-4.15.0+git.1731052905.05fd299e/agents/raritan_px3/fence_raritan_px3.py
     2024-11-08 09:01:45.000000000 +0100
@@ -157,7 +157,7 @@
        docs["vendorurl"] = "http://www.raritan.com/";
        show_docs(options, docs)
 
-       conn = fence_login(options, re_login_string="Username.*")
+       conn = fence_login(options, re_login_string=r"Username.*")
 
        px3_get_outlet_list(conn, options)
        try:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fence-agents-4.15.0+git.1724675137.ca9ae93a/agents/scsi/fence_scsi.py 
new/fence-agents-4.15.0+git.1731052905.05fd299e/agents/scsi/fence_scsi.py
--- old/fence-agents-4.15.0+git.1724675137.ca9ae93a/agents/scsi/fence_scsi.py   
2024-08-26 14:25:37.000000000 +0200
+++ new/fence-agents-4.15.0+git.1731052905.05fd299e/agents/scsi/fence_scsi.py   
2024-11-08 09:01:45.000000000 +0100
@@ -131,11 +131,13 @@
        return run_cmd(options, options["--sg_turs-path"] + " " + dev)["rc"]
 
 
-def register_dev(options, dev, key):
+def register_dev(options, dev, key, do_preempt=True):
        dev = os.path.realpath(dev)
        if re.search(r"^dm", dev[5:]):
-               for slave in get_mpath_slaves(dev):
-                       register_dev(options, slave, key)
+               devices = get_mpath_slaves(dev)
+               register_dev(options, devices[0], key)
+               for device in devices[1:]:
+                       register_dev(options, device, key, False)
                return True
 
        # Check if any registration exists for the key already. We track this in
@@ -153,7 +155,7 @@
                # If key matches, make sure it matches with the connection that
                # exists right now. To do this, we can issue a preempt with 
same key
                # which should replace the old invalid entries from the target.
-               if not preempt(options, key, dev, key):
+               if do_preempt and not preempt(options, key, dev, key):
                        return False
 
                # If there was no reservation, we need to issue another 
registration
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fence-agents-4.15.0+git.1724675137.ca9ae93a/fence-agents.spec.in 
new/fence-agents-4.15.0+git.1731052905.05fd299e/fence-agents.spec.in
--- old/fence-agents-4.15.0+git.1724675137.ca9ae93a/fence-agents.spec.in        
2024-08-26 14:25:37.000000000 +0200
+++ new/fence-agents-4.15.0+git.1731052905.05fd299e/fence-agents.spec.in        
2024-11-08 09:01:45.000000000 +0100
@@ -70,6 +70,7 @@
 fence-agents-lpar \\
 fence-agents-mpath \\
 fence-agents-netio \\
+fence-agents-nutanix-ahv \\
 fence-agents-ovh \\
 fence-agents-ovm \\
 fence-agents-redfish \\
@@ -930,6 +931,18 @@
 %{_sbindir}/fence_netio
 %{_mandir}/man8/fence_netio.8*
 
+%package nutanix-ahv
+License: GPL-2.0-or-later AND LGPL-2.0-or-later
+Summary: Fence agent for Nutanix AHV
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+Obsoletes: fence-agents < 3.1.13
+%description nutanix-ahv
+Fence agent for Nutanix AHV clusters.
+%files nutanix-ahv
+%{_sbindir}/fence_nutanix_ahv
+%{_mandir}/man8/fence_nutanix_ahv.8*
+
 %ifarch x86_64 ppc64le
 %package openstack
 License: GPL-2.0-or-later AND LGPL-2.0-or-later
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fence-agents-4.15.0+git.1724675137.ca9ae93a/lib/fencing.py.py 
new/fence-agents-4.15.0+git.1731052905.05fd299e/lib/fencing.py.py
--- old/fence-agents-4.15.0+git.1724675137.ca9ae93a/lib/fencing.py.py   
2024-08-26 14:25:37.000000000 +0200
+++ new/fence-agents-4.15.0+git.1731052905.05fd299e/lib/fencing.py.py   
2024-11-08 09:01:45.000000000 +0100
@@ -124,7 +124,7 @@
                "getopt" : "l:",
                "longopt" : "username",
                "help" : "-l, --username=[name]          Login name",
-               "required" : "?",
+               "required" : "0",
                "order" : 1},
        "no_login" : {
                "getopt" : "",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fence-agents-4.15.0+git.1724675137.ca9ae93a/tests/data/metadata/fence_ibm_powervs.xml
 
new/fence-agents-4.15.0+git.1731052905.05fd299e/tests/data/metadata/fence_ibm_powervs.xml
--- 
old/fence-agents-4.15.0+git.1724675137.ca9ae93a/tests/data/metadata/fence_ibm_powervs.xml
   2024-08-26 14:25:37.000000000 +0200
+++ 
new/fence-agents-4.15.0+git.1731052905.05fd299e/tests/data/metadata/fence_ibm_powervs.xml
   2024-11-08 09:01:45.000000000 +0100
@@ -1,6 +1,6 @@
 <?xml version="1.0" ?>
 <resource-agent name="fence_ibm_powervs" shortdesc="Fence agent for IBM 
PowerVS" >
-<longdesc>fence_ibm_powervs is a Power Fencing agent which can be used with 
IBM PowerVS to fence virtual machines.</longdesc>
+<longdesc>fence_ibm_powervs is a power fencing agent for IBM Power Virtual 
Server (IBM PowerVS) to fence virtual server instances.</longdesc>
 <vendor-url>https://www.ibm.com</vendor-url>
 <parameters>
        <parameter name="api-type" unique="0" required="0" deprecated="1">
@@ -122,12 +122,12 @@
        </parameter>
        <parameter name="power_timeout" unique="0" required="0">
                <getopt mixed="--power-timeout=[seconds]" />
-               <content type="second" default="30"  />
+               <content type="second" default="120"  />
                <shortdesc lang="en">Test X seconds for status change after 
ON/OFF</shortdesc>
        </parameter>
        <parameter name="power_wait" unique="0" required="0">
                <getopt mixed="--power-wait=[seconds]" />
-               <content type="second" default="1"  />
+               <content type="second" default="15"  />
                <shortdesc lang="en">Wait X seconds after issuing 
ON/OFF</shortdesc>
        </parameter>
        <parameter name="shell_timeout" unique="0" required="0">
@@ -137,7 +137,7 @@
        </parameter>
        <parameter name="stonith_status_sleep" unique="0" required="0">
                <getopt mixed="--stonith-status-sleep=[seconds]" />
-               <content type="second" default="2"  />
+               <content type="second" default="10"  />
                <shortdesc lang="en">Sleep X seconds between status calls 
during a STONITH action</shortdesc>
        </parameter>
        <parameter name="retry_on" unique="0" required="0">
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fence-agents-4.15.0+git.1724675137.ca9ae93a/tests/data/metadata/fence_nutanix_ahv.xml
 
new/fence-agents-4.15.0+git.1731052905.05fd299e/tests/data/metadata/fence_nutanix_ahv.xml
--- 
old/fence-agents-4.15.0+git.1724675137.ca9ae93a/tests/data/metadata/fence_nutanix_ahv.xml
   1970-01-01 01:00:00.000000000 +0100
+++ 
new/fence-agents-4.15.0+git.1731052905.05fd299e/tests/data/metadata/fence_nutanix_ahv.xml
   2024-11-08 09:01:45.000000000 +0100
@@ -0,0 +1,201 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_nutanix_ahv" shortdesc="Fencing agent for Nutanix 
AHV Cluster VMs." >
+<longdesc>fence_ahv is a power fencing agent for virtual machines deployed on 
Nutanix AHV cluster with the AHV cluster being managed by Prism 
Central.</longdesc>
+<vendor-url>https://www.nutanix.com</vendor-url>
+<parameters>
+       <parameter name="action" unique="0" required="1">
+               <getopt mixed="-o, --action=[action]" />
+               <content type="string" default="reboot"  />
+               <shortdesc lang="en">Fencing action</shortdesc>
+       </parameter>
+       <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+               <getopt mixed="-a, --ip=[ip]" />
+               <content type="string"  />
+               <shortdesc lang="en">IP address or hostname of fencing 
device</shortdesc>
+       </parameter>
+       <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+               <getopt mixed="-a, --ip=[ip]" />
+               <content type="string"  />
+               <shortdesc lang="en">IP address or hostname of fencing 
device</shortdesc>
+       </parameter>
+       <parameter name="ipport" unique="0" required="0">
+               <getopt mixed="-u, --ipport=[port]" />
+               <content type="integer" default="80"  />
+               <shortdesc lang="en">TCP/UDP port to use for connection with 
device</shortdesc>
+       </parameter>
+       <parameter name="login" unique="0" required="1" deprecated="1">
+               <getopt mixed="-l, --username=[name]" />
+               <content type="string"  />
+               <shortdesc lang="en">Login name</shortdesc>
+       </parameter>
+       <parameter name="method" unique="0" required="0">
+               <getopt mixed="-m, --method=[method]" />
+               <content type="select" default="onoff"  >
+                       <option value="onoff" />
+                       <option value="cycle" />
+               </content>
+               <shortdesc lang="en">Method to fence</shortdesc>
+       </parameter>
+       <parameter name="notls" unique="0" required="0">
+               <getopt mixed="-t, --notls" />
+               <content type="boolean"  />
+               <shortdesc lang="en">Disable TLS negotiation and force SSL3.0. 
This should only be used for devices that do not support TLS1.0 and 
up.</shortdesc>
+       </parameter>
+       <parameter name="passwd" unique="0" required="0" deprecated="1">
+               <getopt mixed="-p, --password=[password]" />
+               <content type="string"  />
+               <shortdesc lang="en">Login password or passphrase</shortdesc>
+       </parameter>
+       <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+               <getopt mixed="-S, --password-script=[script]" />
+               <content type="string"  />
+               <shortdesc lang="en">Script to run to retrieve 
password</shortdesc>
+       </parameter>
+       <parameter name="password" unique="0" required="0" obsoletes="passwd">
+               <getopt mixed="-p, --password=[password]" />
+               <content type="string"  />
+               <shortdesc lang="en">Login password or passphrase</shortdesc>
+       </parameter>
+       <parameter name="password_script" unique="0" required="0" 
obsoletes="passwd_script">
+               <getopt mixed="-S, --password-script=[script]" />
+               <content type="string"  />
+               <shortdesc lang="en">Script to run to retrieve 
password</shortdesc>
+       </parameter>
+       <parameter name="plug" unique="0" required="1" obsoletes="port">
+               <getopt mixed="-n, --plug=[id]" />
+               <content type="string"  />
+               <shortdesc lang="en">Physical plug number on device, UUID or 
identification of machine</shortdesc>
+       </parameter>
+       <parameter name="port" unique="0" required="1" deprecated="1">
+               <getopt mixed="-n, --plug=[id]" />
+               <content type="string"  />
+               <shortdesc lang="en">Physical plug number on device, UUID or 
identification of machine</shortdesc>
+       </parameter>
+       <parameter name="ssl" unique="0" required="0">
+               <getopt mixed="-z, --ssl" />
+               <content type="boolean"  />
+               <shortdesc lang="en">Use SSL connection with verifying 
certificate</shortdesc>
+       </parameter>
+       <parameter name="ssl_insecure" unique="0" required="0">
+               <getopt mixed="--ssl-insecure" />
+               <content type="boolean"  />
+               <shortdesc lang="en">Use SSL connection without verifying 
certificate</shortdesc>
+       </parameter>
+       <parameter name="ssl_secure" unique="0" required="0">
+               <getopt mixed="--ssl-secure" />
+               <content type="boolean"  />
+               <shortdesc lang="en">Use SSL connection with verifying 
certificate</shortdesc>
+       </parameter>
+       <parameter name="username" unique="0" required="1" obsoletes="login">
+               <getopt mixed="-l, --username=[name]" />
+               <content type="string"  />
+               <shortdesc lang="en">Login name</shortdesc>
+       </parameter>
+       <parameter name="filter" unique="0" required="0">
+               <getopt mixed="
+            --filter=[filter]" />
+               <content type="string"  />
+               <shortdesc lang="en">Filter list, get_liste.g: "name eq 
'node1-vm'"</shortdesc>
+       </parameter>
+       <parameter name="quiet" unique="0" required="0">
+               <getopt mixed="-q, --quiet" />
+               <content type="boolean"  />
+               <shortdesc lang="en">Disable logging to stderr. Does not affect 
--verbose or --debug-file or logging to syslog.</shortdesc>
+       </parameter>
+       <parameter name="verbose" unique="0" required="0">
+               <getopt mixed="-v, --verbose" />
+               <content type="boolean"  />
+               <shortdesc lang="en">Verbose mode. Multiple -v flags can be 
stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+       </parameter>
+       <parameter name="verbose_level" unique="0" required="0">
+               <getopt mixed="--verbose-level" />
+               <content type="integer"  />
+               <shortdesc lang="en">Level of debugging detail in output. 
Defaults to the number of --verbose flags specified on the command line, or to 
1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+       </parameter>
+       <parameter name="debug" unique="0" required="0" deprecated="1">
+               <getopt mixed="-D, --debug-file=[debugfile]" />
+               <content type="string"  />
+               <shortdesc lang="en">Write debug information to given 
file</shortdesc>
+       </parameter>
+       <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+               <getopt mixed="-D, --debug-file=[debugfile]" />
+               <shortdesc lang="en">Write debug information to given 
file</shortdesc>
+       </parameter>
+       <parameter name="version" unique="0" required="0">
+               <getopt mixed="-V, --version" />
+               <content type="boolean"  />
+               <shortdesc lang="en">Display version information and 
exit</shortdesc>
+       </parameter>
+       <parameter name="help" unique="0" required="0">
+               <getopt mixed="-h, --help" />
+               <content type="boolean"  />
+               <shortdesc lang="en">Display help and exit</shortdesc>
+       </parameter>
+       <parameter name="plug_separator" unique="0" required="0">
+               <getopt mixed="--plug-separator=[char]" />
+               <content type="string" default=","  />
+               <shortdesc lang="en">Separator for plug parameter when 
specifying more than 1 plug</shortdesc>
+       </parameter>
+       <parameter name="separator" unique="0" required="0">
+               <getopt mixed="-C, --separator=[char]" />
+               <content type="string" default=","  />
+               <shortdesc lang="en">Separator for CSV created by 'list' 
operation</shortdesc>
+       </parameter>
+       <parameter name="delay" unique="0" required="0">
+               <getopt mixed="--delay=[seconds]" />
+               <content type="second" default="0"  />
+               <shortdesc lang="en">Wait X seconds before fencing is 
started</shortdesc>
+       </parameter>
+       <parameter name="disable_timeout" unique="0" required="0">
+               <getopt mixed="--disable-timeout=[true/false]" />
+               <content type="string"  />
+               <shortdesc lang="en">Disable timeout (true/false) (default: 
true when run from Pacemaker 2.0+)</shortdesc>
+       </parameter>
+       <parameter name="login_timeout" unique="0" required="0">
+               <getopt mixed="--login-timeout=[seconds]" />
+               <content type="second" default="5"  />
+               <shortdesc lang="en">Wait X seconds for cmd prompt after 
login</shortdesc>
+       </parameter>
+       <parameter name="power_timeout" unique="0" required="0">
+               <getopt mixed="--power-timeout=[seconds]" />
+               <content type="second" default="60"  />
+               <shortdesc lang="en">Test X seconds for status change after 
ON/OFF</shortdesc>
+       </parameter>
+       <parameter name="power_wait" unique="0" required="0">
+               <getopt mixed="--power-wait=[seconds]" />
+               <content type="second" default="0"  />
+               <shortdesc lang="en">Wait X seconds after issuing 
ON/OFF</shortdesc>
+       </parameter>
+       <parameter name="shell_timeout" unique="0" required="0">
+               <getopt mixed="--shell-timeout=[seconds]" />
+               <content type="second" default="3"  />
+               <shortdesc lang="en">Wait X seconds for cmd prompt after 
issuing command</shortdesc>
+       </parameter>
+       <parameter name="stonith_status_sleep" unique="0" required="0">
+               <getopt mixed="--stonith-status-sleep=[seconds]" />
+               <content type="second" default="1"  />
+               <shortdesc lang="en">Sleep X seconds between status calls 
during a STONITH action</shortdesc>
+       </parameter>
+       <parameter name="retry_on" unique="0" required="0">
+               <getopt mixed="--retry-on=[attempts]" />
+               <content type="integer" default="1"  />
+               <shortdesc lang="en">Count of attempts to retry power 
on</shortdesc>
+       </parameter>
+       <parameter name="gnutlscli_path" unique="0" required="0">
+               <getopt mixed="--gnutlscli-path=[path]" />
+               <shortdesc lang="en">Path to gnutls-cli binary</shortdesc>
+       </parameter>
+</parameters>
+<actions>
+       <action name="on" automatic="0"/>
+       <action name="off" />
+       <action name="reboot" />
+       <action name="status" />
+       <action name="list" />
+       <action name="list-status" />
+       <action name="monitor" />
+       <action name="metadata" />
+       <action name="manpage" />
+       <action name="validate-all" />
+</actions>
+</resource-agent>

Reply via email to