Change in vdsm[ovirt-3.5]: fencing: Skip fencing if host is maintaining its lease

mperina at redhat.com mperina at redhat.com
Fri Aug 8 08:54:58 UTC 2014


Martin Peřina has uploaded a new change for review.

Change subject: fencing: Skip fencing if host is maintaining its lease
......................................................................

fencing: Skip fencing if host is maintaining its lease

1) Adds fencingPolicy parameter to fenceNode API call. The parameter is
   optional, but it's supposed to be used in oVirt >= 3.5.
2) fencingPolicy parameter can contain storageDomainHostIdMap, which
   is a map of storage domains and host ids
3) If clusterlock reports that host is live on at least one of specified
   storage domains, the fence agent execution is skipped and host is
   considered alive

Change-Id: I7b1fd9521cebea28d0402e53d46d74b95e73f383
Bug-Url: https://bugzilla.redhat.com/1090799
Signed-off-by: Martin Perina <mperina at redhat.com>
---
M vdsm/API.py
M vdsm/rpc/BindingXMLRPC.py
M vdsm/rpc/vdsmapi-schema.json
3 files changed, 89 insertions(+), 12 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/30/31230/1

diff --git a/vdsm/API.py b/vdsm/API.py
index f328a0b..f2d8878 100644
--- a/vdsm/API.py
+++ b/vdsm/API.py
@@ -1122,7 +1122,7 @@
 
     # General Host functions
     def fenceNode(self, addr, port, agent, username, password, action,
-                  secure=False, options=''):
+                  secure=False, options='', policy=None):
         """Send a fencing command to a remote node.
 
            agent is one of (rsa, ilo, drac5, ipmilan, etc)
@@ -1148,12 +1148,48 @@
                 cleantext += line
             return cleantext
 
+        def should_fence(policy):
+            # skip fence execution if map of storage domains with host id is
+            # entered and at least one storage domain connection from host is
+            # alive
+            if policy is None:
+                self.log.debug('No policy specified')
+                return True
+
+            hostIdMap = policy.get('storageDomainHostIdMap')
+            if not hostIdMap:
+                self.log.warning('Invalid policy specified')
+                return True
+
+            result = self._irs.getHostLeaseStatus(hostIdMap)
+            if result['status']['code'] != 0:
+                self.log.error(
+                    "Error getting host lease status, error code '%s'",
+                    result['status']['code'])
+                return True
+
+            # HOST_STATUS_LIVE means that host renewed its lease in last 80
+            # seconds. If so, we consider the host Up and we won't execute
+            # fencing, even when it's unreachable from engine
+            for sd, status in result['domains'].iteritems():
+                if status == storage.clusterlock.HOST_STATUS_LIVE:
+                    self.log.debug("Host has live lease on '%s'", sd)
+                    return False
+
+            self.log.debug("Host doesn't have any live lease")
+            return True
+
         self.log.debug('fenceNode(addr=%s,port=%s,agent=%s,user=%s,passwd=%s,'
-                       'action=%s,secure=%s,options=%s)', addr, port, agent,
-                       username, 'XXXX', action, secure, options)
+                       'action=%s,secure=%s,options=%s,policy=%s)',
+                       addr, port, agent, username, 'XXXX', action, secure,
+                       options, policy)
 
         if action not in ('status', 'on', 'off', 'reboot'):
             raise ValueError('illegal action ' + action)
+
+        if action != 'status' and not should_fence(policy):
+            self.log.debug("Skipping execution of action '%s'", action)
+            return {'status': doneCode, 'operationStatus': 'skipped'}
 
         script = constants.EXT_FENCE_PREFIX + agent
 
@@ -1188,7 +1224,8 @@
             return {'status': {'code': 0, 'message': message},
                     'power': power}
         threading.Thread(target=fence, args=(script, inp)).start()
-        return {'status': doneCode, 'power': 'unknown'}
+        return {'status': doneCode, 'power': 'unknown',
+                'operationStatus': 'initiated'}
 
     def ping(self):
         "Ping the server. Useful for tests"
diff --git a/vdsm/rpc/BindingXMLRPC.py b/vdsm/rpc/BindingXMLRPC.py
index 30fc73c..12a1b49 100644
--- a/vdsm/rpc/BindingXMLRPC.py
+++ b/vdsm/rpc/BindingXMLRPC.py
@@ -563,10 +563,10 @@
         return api.setSafeNetworkConfig()
 
     def fenceNode(self, addr, port, agent, username, password, action,
-                  secure=False, options=''):
+                  secure=False, options='', policy=None):
         api = API.Global()
         return api.fenceNode(addr, port, agent, username, password, action,
-                             secure, options)
+                             secure, options, policy)
 
     def setLogLevel(self, level):
         api = API.Global()
diff --git a/vdsm/rpc/vdsmapi-schema.json b/vdsm/rpc/vdsmapi-schema.json
index c301912..53c59c5 100644
--- a/vdsm/rpc/vdsmapi-schema.json
+++ b/vdsm/rpc/vdsmapi-schema.json
@@ -276,9 +276,9 @@
 {'enum': 'FenceNodeAction', 'data': ['status', 'on', 'off', 'reboot']}
 
 ##
-# @FenceNodePowerStatus:
+# @FenceNodeResult:
 #
-# Indicates the power state of a remote host.
+# For 'status' action, the result is the power status of the host
 #
 # @on:       The remote host is powered on
 #
@@ -287,8 +287,45 @@
 # @unknown:  The power status is not known
 #
 # Since: 4.10.0
+#
+# For 'on', 'off' and 'reboot', the result is status of fence script execution
+#
+# @initiated:   Fence script was executed
+#
+# @skipped:     Fence script was not executed due to entered fencing policy
+#
+# Since: 4.16.0
 ##
-{'enum': 'FenceNodePowerStatus', 'data': ['on', 'off', 'unknown']}
+{'enum': 'FenceNodeResult', 'data': ['on', 'off', 'unknown', 'initiated',
+                                     'skipped']}
+
+##
+# @HostIdMap:
+#
+# A mapping of hostId indexed by domain UUID.
+#
+# Since: 4.16.0
+##
+{'map': 'HostIdMap',
+ 'key': 'UUID', 'value': 'int'}
+
+##
+# @FencingPolicy:
+#
+# Additional options for fenceNode logic.
+#
+# @storageDomainHostIdMap:   #optional map of storage domains and host ids.
+#                            It is used to check status of host lease on
+#                            specified storage. If host has live lease on
+#                            at least one storage domain, then fence actions
+#                            'on', 'off' and 'reboot' will not be executed.
+#                            The 'status' action execution is unaffected by
+#                            content of the map.
+#
+# Since: 4.16.0
+##
+{'type': 'FencingPolicy',
+ 'data': {'*storageDomainHostIdMap': 'HostIdMap'}}
 
 ##
 # @Host.fenceNode:
@@ -313,16 +350,19 @@
 # @options:   #optional Additional agent-specific parameters in space-separated
 #             <var>=<val> pairs
 #
+# @policy:    #optional Additional options needed in fenceNode logic
+#             (new in version 4.16.0)
+#
 # Returns:
-# The new power status of the remote node
+# Result of specified fence action
 #
 # Since: 4.10.0
 ##
 {'command': {'class': 'Host', 'name': 'fenceNode'},
  'data': {'addr': 'str', 'port': 'int', 'agent': 'str', 'username': 'str',
           'password': 'str', 'action': 'FenceNodeAction', '*secure': 'bool',
-          '*options': 'str'},
- 'returns': 'FenceNodePowerStatus'}
+          '*options': 'str', '*policy': 'FencingPolicy'},
+ 'returns': 'FenceNodeResult'}
 
 ##
 # @TaskInfo:


-- 
To view, visit http://gerrit.ovirt.org/31230
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I7b1fd9521cebea28d0402e53d46d74b95e73f383
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: ovirt-3.5
Gerrit-Owner: Martin Peřina <mperina at redhat.com>


More information about the vdsm-patches mailing list