Hi Hans, Thanks for your ack. I run pylint with pylintrc in opensaf-code/python directory: pylint --rcfile=python/pylintrc python/samples/clm-tool
Thanks, /Danh -----Original Message----- From: Hans Nordebäck [mailto:[email protected]] Sent: Tuesday, December 19, 2017 6:35 PM To: Danh Vo <[email protected]>; [email protected]; [email protected] Cc: [email protected] Subject: Re: [PATCH 1/1] pyosaf: Refactor clm-tool sample to make use of new pyosaf utils [#2679] 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
