ack with a question, (review only). Have you run pylint on clm-tool? There are new remarks such as Invalid variable name, Invalid constant name, Too many arguments, etc.

/Thanks HansN


On 12/04/2017 08:46 AM, Danh Vo wrote:
- Refactor clm-tool.
- Add new function in clm util for sending node get.
---
  python/pyosaf/utils/clm/__init__.py | 125 +++++++++------
  python/samples/clm-tool             | 309 ++++++++++++++++++++++++++++--------
  2 files changed, 322 insertions(+), 112 deletions(-)

diff --git a/python/pyosaf/utils/clm/__init__.py 
b/python/pyosaf/utils/clm/__init__.py
index 533a4b5..5461d4a 100644
--- a/python/pyosaf/utils/clm/__init__.py
+++ b/python/pyosaf/utils/clm/__init__.py
@@ -44,6 +44,38 @@ saClmClusterNodeGetAsync = 
decorate(saClm.saClmClusterNodeGetAsync)
  saClmResponse_4 = decorate(saClm.saClmResponse_4)
+class ClusterNode(object):
+    """ Class representing a CLM cluster node """
+
+    def __init__(self, node_id, node_address, node_name, execution_environment,
+                 member, boot_timestamp, initial_view_number):
+        """ Constructor for ClusterNode class
+
+        Args:
+            node_id (SaClmNodeIdT): Node identifier
+            node_address (SaClmNodeAddressT): Node network communication
+                address
+            node_name (SaNameT): Node name
+            execution_environment (SaNameT): DN of the PLM execution
+                environment that hosts the node
+            member (SaBoolT): Indicate whether this is a CLM member node (True)
+                or not (False)
+            boot_timestamp (SaTimeT): Timestamp at which the node was last
+                booted
+            initial_view_number (SaUint64T): View number of the latest
+                membership transition when this configured node joined the
+                cluster membership
+        """
+        self.node_id = node_id
+        self.node_address_value = node_address.value
+        self.node_address_family = node_address.family
+        self.node_name = node_name.value
+        self.execution_environment = execution_environment
+        self.member = member
+        self.boot_timestamp = boot_timestamp
+        self.initial_view_number = initial_view_number
+
+
  class ClmAgentManager(object):
      """ This class manages the life cycle of a CLM agent, and also acts as
      a proxy handler for CLM callbacks """
@@ -105,7 +137,7 @@ class ClmAgentManager(object):
                  notification = notification_buffer.notification[i]
                  clm_cluster_node = notification.clusterNode
                  cluster_node = \
-                    create_cluster_node_instance(clm_cluster_node)
+                    self.create_cluster_node_instance(clm_cluster_node)
                  node_state = (cluster_node, notification.clusterChange)
node_list.append(node_state)
@@ -133,7 +165,7 @@ class ClmAgentManager(object):
              error = c_error
cluster_node = \
-                create_cluster_node_instance(c_cluster_node.contents)
+                self.create_cluster_node_instance(c_cluster_node.contents)
# Send the node info to user's callback function
              self.node_get_function(invocation, cluster_node, error)
@@ -221,7 +253,7 @@ class ClmAgentManager(object):
              rc = saClmFinalize(self.handle)
              if rc != eSaAisErrorT.SA_AIS_OK:
                  log_err("saClmFinalize FAILED - %s" % eSaAisErrorT.whatis(rc))
-            elif rc == eSaAisErrorT.SA_AIS_OK \
+            if rc == eSaAisErrorT.SA_AIS_OK \
                      or rc == eSaAisErrorT.SA_AIS_ERR_BAD_HANDLE:
                  # If the Finalize() call returned BAD_HANDLE, the handle 
should
                  # already become stale and invalid, so we reset it anyway.
@@ -229,6 +261,25 @@ class ClmAgentManager(object):
return rc + @staticmethod
+    def create_cluster_node_instance(clm_cluster_node):
+        """ Create ClusterNode object from cluster node information
+
+        Args:
+            clm_cluster_node (SaClmClusterNodeT): Cluster node information
+
+        Returns:
+            ClusterNode: An object containing cluster node information
+        """
+        return ClusterNode(
+            node_id=clm_cluster_node.nodeId,
+            node_address=clm_cluster_node.nodeAddress,
+            node_name=clm_cluster_node.nodeName,
+            execution_environment=clm_cluster_node.executionEnvironment,
+            member=clm_cluster_node.member,
+            boot_timestamp=clm_cluster_node.bootTimestamp,
+            initial_view_number=clm_cluster_node.initialViewNumber)
+
class ClmAgent(ClmAgentManager):
      """ This class acts as a high-level CLM agent, providing CLM functions to
@@ -327,7 +378,8 @@ class ClmAgent(ClmAgentManager):
                  notification = notification_buffer.notification[i]
                  clm_cluster_node = notification.clusterNode
- cluster_node = create_cluster_node_instance(clm_cluster_node)
+                cluster_node = \
+                    self.create_cluster_node_instance(clm_cluster_node)
cluster_nodes.append(cluster_node)
          else:
@@ -379,7 +431,7 @@ class ClmAgent(ClmAgentManager):
          """
          rc = saClmClusterTrackStop(self.handle)
          if rc != eSaAisErrorT.SA_AIS_OK:
-            log_err("saClmClusterTrack_4 FAILED - %s" %
+            log_err("saClmClusterTrackStop FAILED - %s" %
                      eSaAisErrorT.whatis(rc))
if rc == eSaAisErrorT.SA_AIS_ERR_BAD_HANDLE:
@@ -415,56 +467,29 @@ class ClmAgent(ClmAgentManager):
return rc -
-class ClusterNode(object):
-    """ Class representing a CLM cluster node """
-
-    def __init__(self, node_id, node_address, node_name, execution_environment,
-                 member, boot_timestamp, initial_view_number):
-        """ Constructor for ClusterNode class
+    def get_node_info(self, node_id, time_out):
+        """ Get information of a specific cluster member node.
Args:
-            node_id (SaClmNodeIdT): Node identifier
-            node_address (SaClmNodeAddressT): Node network communication
-                address
-            node_name (SaNameT): Node name
-            execution_environment (SaNameT): DN of the PLM execution
-                environment that hosts the node
-            member (SaBoolT): Indicate whether this is a CLM member node (True)
-                or not (False)
-            boot_timestamp (SaTimeT): Timestamp at which the node was last
-                booted
-            initial_view_number (SaUint64T): View number of the latest
-                membership transition when this configured node joined the
-                cluster membership
-        """
-        self.node_id = node_id
-        self.node_address_value = node_address.value
-        self.node_address_family = node_address.family
-        self.node_name = node_name.value
-        self.execution_environment = execution_environment
-        self.member = member
-        self.boot_timestamp = boot_timestamp
-        self.initial_view_number = initial_view_number
-
+            node_id (SaClmNodeIdT): Node id
+            time_out (SaTimeT): Time-out (in nanosecond) for
+                saClmClusterNodeGet_4 operation
-def create_cluster_node_instance(clm_cluster_node):
-    """ Create ClusterNode object from cluster node information
+        Returns:
+            SaAisErrorT: Return code of the saClmClusterNodeGet_4() API call.
+            ClusterNode: Node info or None if node with `node id` is not found.
+        """
+        clm_cluster_node = saClm.SaClmClusterNodeT_4()
- Args:
-        clm_cluster_node (SaClmClusterNodeT): Cluster node information
+        rc = saClmClusterNodeGet_4(self.handle, node_id, time_out,
+                                   clm_cluster_node)
+        if rc != eSaAisErrorT.SA_AIS_OK:
+            log_err("saClmClusterNodeGet() FAILED - %s" %
+                    eSaAisErrorT.whatis(rc))
+            return rc, None
- Returns:
-        ClusterNode: An object containing cluster node information
-    """
-    return ClusterNode(
-        node_id=clm_cluster_node.nodeId,
-        node_address=clm_cluster_node.nodeAddress,
-        node_name=clm_cluster_node.nodeName,
-        execution_environment=clm_cluster_node.executionEnvironment,
-        member=clm_cluster_node.member,
-        boot_timestamp=clm_cluster_node.bootTimestamp,
-        initial_view_number=clm_cluster_node.initialViewNumber)
+        cluster_node = self.create_cluster_node_instance(clm_cluster_node)
+        return rc, cluster_node
@deprecate
diff --git a/python/samples/clm-tool b/python/samples/clm-tool
index 89bf0d3..60dcc8f 100755
--- a/python/samples/clm-tool
+++ b/python/samples/clm-tool
@@ -1,67 +1,252 @@
  #!/usr/bin/env python
-
+############################################################################
+#
+# (C) Copyright 2015 The OpenSAF Foundation
+# (C) Copyright 2017 Ericsson AB. All rights reserved.
+#
+# 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. This file and program are licensed
+# under the GNU Lesser General Public License Version 2.1, February 1999.
+# The complete license can be accessed from the following location:
+# http://opensource.org/licenses/lgpl-license.php
+# See the Copying file included with the OpenSAF distribution for full
+# licensing terms.
+#
+# Author(s): Ericsson
+#
+############################################################################
+"""
+This is a SAF CLM utility which supports options to:
+    - Retrieve information about one or all CLM cluster member nodes.
+    - Track CLM cluster membership changes.
+    - Run clm-tool --help/-h for more detail on usage.
+"""
+from __future__ import print_function
  import argparse
  import sys
+from select import select
-from pyosaf import saAis, saClm, saImm
-
+from pyosaf.saAis import saAis, eSaAisErrorT, eSaDispatchFlagsT
  from pyosaf.utils import clm
-
-def dn_to_vm_name(vm_dn):
-    return vm_dn.split(',')[0].split('=')[1]
-
-def print_members(members):
-
-    for node in members:
-        if node.member:
-            vm_name    = dn_to_vm_name(node.node_name)
-            ip_address = node.node_address_value
-
-            print "  - %s  %s" % (vm_name, ip_address)
-
-def membership_change(added, removed):
-    print "Info: Received cluster membership update"
-
-    for node in added:
-        vm_name = dn_to_vm_name(node.node_name)
-
-        print "INFO: %s joined the cluster" % vm_name
-
-    for node in removed:
-        vm_name = dn_to_vm_name(node.node_name)
-
-        print "INFO: %s left the cluster" % vm_name
-
-
-if __name__ == "__main__":
-
-    # Parse command line arguments
-    parser = argparse.ArgumentParser(
-        description='Listens to changes to objects of the given classes')
-
-    group = parser.add_mutually_exclusive_group(required=True)
-
-    group.add_argument('--snapshot', action="store_true",
-                        help='shows a snapshot of the current membership list')
-    group.add_argument('--listen', action="store_true", help='listens to 
changes to all classes')
-
-    args = parser.parse_args()
-
-    # Initialize the CLM service
-    clm.initialize(track_fn=membership_change)
-
-    if args.snapshot:
-        print "-" * 10 + " Members " + "-"*10
-
-        members = clm.get_members()
-
-        print_members(members)
-
-        sys.exit(0)
-
-    # Start tracking
-    clm.track()
-
-    # Do dispatch forever
-    while True:
-        clm.saClmDispatch(clm.HANDLE, 
saAis.eSaDispatchFlagsT.SA_DISPATCH_BLOCKING)
+from pyosaf.utils.immom.accessor import ImmOmAccessor
+
+
+class ClmTool(object):
+    """ This class provides functions of the clm-tool. """
+    def __init__(self):
+        self.clm_agent = clm.ClmAgent()
+        self.clm_agent.init(self.membership_change)
+        self.sel_obj = self.clm_agent.get_selection_object()
+
+    def print_members(self):
+        """ Print out the name and the IP address of all current member nodes.
+
+        Returns:
+            Boolean: True if cluster members info is printed successfully.
+                Otherwise, it is False.
+
+        """
+        print("-" * 10 + " Members " + "-" * 10)
+        rc, members = self.clm_agent.get_members()
+        if rc != eSaAisErrorT.SA_AIS_OK:
+            print("Failed to get current membership. rc:",
+                  eSaAisErrorT.whatis(rc))
+            return False
+        else:
+            for node in members:
+                node_name = self.node_dn_to_node_name(node.node_name)
+                ip_address = node.node_address_value
+                print("  - %s  %s" % (node_name, ip_address))
+
+        return True
+
+    def request_node_info(self, node_dn, time_out):
+        """ Request the information of a specific member node which is
+        identified by its DN.
+
+        Args:
+            node_dn (str): The DN of SaClmNode class's object.
+            time_out (int): Timeout in nanosecond.
+
+        Returns:
+            ClusterNode: Node info or None if node with `node_dn` is not found.
+        """
+        accessor = ImmOmAccessor()
+        accessor.init()
+
+        rc, clm_node_object = accessor.get(node_dn)
+        if rc != eSaAisErrorT.SA_AIS_OK:
+            print("%s object does not exist" % node_dn)
+            return None
+
+        node_id = clm_node_object["saClmNodeID"]
+        rc, mem_node_info = self.clm_agent.get_node_info(node_id, time_out)
+        if rc != eSaAisErrorT.SA_AIS_OK:
+            print("Failed to request node info. rc:", eSaAisErrorT.whatis(rc))
+            return None
+
+        return mem_node_info
+
+    def start_tracking(self, track_type):
+        """ Start tracking member nodes.
+
+        Args:
+            track_type (SaUint8T): Type of cluster membership tracking
+
+        Returns:
+            Boolean: True if it starts tracking successfully. Otherwise, it is
+                False.
+        """
+        rc = self.clm_agent.track_start(track_type)
+        if rc != eSaAisErrorT.SA_AIS_OK:
+            print("Failed to start tracking. rc:", eSaAisErrorT.whatis(rc))
+            return False
+
+        return True
+
+    def stop_tracking(self):
+        """ Stop tracking member nodes.
+
+        Returns:
+            Boolean: True if it stops tracking successfully. Otherwise, it is
+                False.
+        """
+        rc = self.clm_agent.track_stop()
+        if rc != eSaAisErrorT.SA_AIS_OK:
+            print("Failed to stop tracking. rc:", eSaAisErrorT.whatis(rc))
+            return False
+
+        return True
+
+    def dispatch(self, dispatch_flag):
+        """ Dispatch message to appropriate callback.
+
+        Args:
+            dispatch_flag (eSaDispatchFlagsT): Flags specifying dispatch mode.
+
+        Returns:
+            Boolean: True if it dispatches message successfully. Otherwise, it
+                is False.
+        """
+        rc = self.clm_agent.dispatch(dispatch_flag)
+        if rc != eSaAisErrorT.SA_AIS_OK:
+            print("Failed to dispatch message. rc:", eSaAisErrorT.whatis(rc))
+            return False
+
+        return True
+
+    def finalize(self):
+        """ Finalize the clm agent.
+
+        Returns:
+            Boolean: True if it clm agent finalizes successfully. Otherwise, it
+                is False.
+        """
+        rc = self.clm_agent.finalize()
+        if rc != eSaAisErrorT.SA_AIS_OK:
+            print("Failed to finalize ClmAgent. rc:", eSaAisErrorT.whatis(rc))
+            return False
+
+        return True
+
+    def membership_change(self, node_list, invocation, step,
+                          num_of_members, error):
+        """ Callback to handle membership change event.
+
+        Args:
+            node_list (tuple): A list of tuple which contain cluster node info
+                and cluster node change type.
+            invocation (SaInvocationT):  A particular invocation of the
+                callback function.
+            step (SaClmChangeStepT): Indicates the tracking step in which
+                the callback is invoked.
+            num_of_members (SaUint32T): The current number of members in the
+                cluster membership.
+            error (SaAisErrorT): indicates if the CLM was able to perform the
+                requested operation.
+        """
+
+        print('-' * 10 + 'Membership Change' + '-' * 10)
+        print("Changed nodes:")
+        for node in node_list:
+            self.print_node_info(node[0])
+            print("\tNode change state:", node[1])
+            print("\t" + "-" * 10)
+
+        print("Invocation:", invocation)
+        print("Step:", step)
+        print("Number of members:", num_of_members)
+        print("Error code:", eSaAisErrorT.whatis(error))
+
+    @staticmethod
+    def print_node_info(cluster_node):
+        """ Print information of a cluster node.
+
+        Args:
+            cluster_node (ClusterNode): ClusterNode object which is printed.
+        """
+        print("\tNode ID:", cluster_node.node_id)
+        print("\tNode Address:", cluster_node.node_address_value)
+        print("\tNode Address Family:", cluster_node.node_address_family)
+        print("\tNode Name:", cluster_node.node_name)
+        print("\tExecution Environment:",
+              'None' if cluster_node.execution_environment.length == 0
+              else cluster_node.execution_environment.value)
+        print("\tMember:", 'Yes' if cluster_node.member == 1 else 'No')
+        print("\tBoot Timestamp:", cluster_node.boot_timestamp)
+        print("\tView Number:", cluster_node.initial_view_number)
+
+    @staticmethod
+    def node_dn_to_node_name(node_dn):
+        """ Convert from node's DN to node's name.
+
+        Args:
+            node_dn (str): DN of a SaClmNode object.
+
+        Returns:
+            str: Name of node.
+        """
+        return node_dn.split(',')[0].split('=')[1]
+
+
+# Main
+parser = argparse.ArgumentParser(description='This is a SAF CLM utility used '
+                                             'to view/track CLM cluster '
+                                             'membership.')
+group = parser.add_mutually_exclusive_group(required=True)
+group.add_argument('-s', '--show', action="store_true",
+                   help='print info of all current cluster member nodes.')
+group.add_argument('-n', '--nodeinfo', type=str,
+                   help="print info of a specific cluster member node.")
+group.add_argument('-t', '--track', action="store_true",
+                   help='track changes in cluster membership.')
+
+clm_tool = ClmTool()
+result = True
+
+args = parser.parse_args()
+if args.show:
+    result = clm_tool.print_members()
+elif args.nodeinfo:
+    node_info = clm_tool.request_node_info(args.nodeinfo, 6000000000)
+    if node_info is not None:
+        clm_tool.print_node_info(node_info)
+    else:
+        result = False
+elif args.track:
+    fds = [clm_tool.sel_obj.value]
+    result = clm_tool.start_tracking(saAis.SA_TRACK_CHANGES)
+
+    try:
+        while result:
+            ioe = select(fds, [], [])
+            for fd in ioe[0]:
+                if fd == clm_tool.sel_obj.value:
+                    result = clm_tool.dispatch(
+                        eSaDispatchFlagsT.SA_DISPATCH_ALL)
+    except KeyboardInterrupt:
+        clm_tool.stop_tracking()
+
+clm_tool.finalize()
+sys.exit(0 if result else 1)


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to