python/samples/README                                       |   47 +++
 python/samples/caps                                         |   42 +++
 python/samples/caps-inheritance-impl                        |   49 +++
 python/samples/imm-listener                                 |  111 ++++++++
 python/samples/imm-listener-inheritance-impl                |  158 ++++++++++++
 python/samples/immoi/samples/caps                           |   42 ---
 python/samples/immoi/samples/caps-inheritance-impl          |   49 ---
 python/samples/immoi/samples/imm-listener                   |  111 --------
 python/samples/immoi/samples/imm-listener-inheritance-impl  |  158 ------------
 python/samples/immoi/samples/ping-pong                      |   59 ----
 python/samples/immoi/samples/ping-pong-inheritance-impl     |   53 ----
 python/samples/immoi/samples/time-reporter                  |   67 -----
 python/samples/immoi/samples/time-reporter-inheritance-impl |   82 ------
 python/samples/immoi/samples/tones                          |   27 --
 python/samples/immoi/samples/tones-inheritance-impl         |   32 --
 python/samples/immoi/samples/users                          |   30 --
 python/samples/immoi/samples/users-inheritance-impl         |   34 --
 python/samples/ping-pong                                    |   59 ++++
 python/samples/ping-pong-inheritance-impl                   |   53 ++++
 python/samples/time-reporter                                |   67 +++++
 python/samples/time-reporter-inheritance-impl               |   82 ++++++
 python/samples/tones                                        |   27 ++
 python/samples/tones-inheritance-impl                       |   32 ++
 python/samples/users                                        |   30 ++
 python/samples/users-inheritance-impl                       |   34 ++
 25 files changed, 791 insertions(+), 744 deletions(-)


Move the sample OIs to the same directory as the existing samples. Also merge 
the separate OI README with the existing README for samples.

diff --git a/python/samples/README b/python/samples/README
--- a/python/samples/README
+++ b/python/samples/README
@@ -22,4 +22,51 @@ clm-tool:
         current members of the cluster and how to monitor changes to the 
         cluster. Run 'clm-tool --help' for specific options and arguments.
 
+imm-listener: 
+        The Imm Lister OI demonstrates how to build an
+        applier. It listens to changes to SampleClass1 and simply
+        prints them on stdout. It's an applier which means that it
+        does not validate any of the changes and it can be run in
+        parallel with a proper OI. Run 'imm-listener --help' for
+        specific options and arguments.
+
+tones:
+        The Tones OI demonstrates validation of containment
+        relations. It implements classes for the tones Do, Re, Mi, Fa,
+        So, La, Ti and only allows creation of each tone under the
+        lower tone, except for Do which can be created without a
+        parent. Run 'tones --help' for specific options and arguments.
+
+caps:
+        The Caps OI demonstrates validation. It validates that any new
+        CapsSample objects and any updated CapsSample objects follow
+        the rules that the upperCaps attribute consists only of
+        uppercase characters and the lowerCaps attribute consists only
+        of lowercase characters. Run 'caps --help' for specific
+        options and arguments.
+
+time-reporter:
+        The Time Reporter OI demonstrates update of runtime attributes
+        from an OI and inclusion of the OI logic into a select loop
+        owned by the application. It creates a runtime object timeId=1
+        of the class TimeSample and updates its hours, minutes and
+        seconds attributes once every second. 
+        Run 'time-reporter --help' for specific options and arguments
+
+ping-pong:
+        The Ping Pong OI demonstrates administrative operations. It
+        creates an object pingPongId=1 and responds on admin
+        operations 0 and 1. Run 'ping-pong --help' for specific
+        options and arguments.
+
+users:
+        The Users OI demonstrates an OI that returns values of runtime
+        attributes when it's queried by IMM. It uses the Python
+        package psutil to fill in the list of logged in users. Run
+        'users --help' for specific options and arguments.
+
 Logging for all apps/utils goes to /var/log/opensaf/saflog/saLogSystem*.log
+
+The IMM OI samples use the classes defined in the classes.xml file. Load it 
with immcfg -f classes.xml before trying them. 
+
+Each sample OI is implemented in two versions, one using straight callbacks 
and one using a class that subclasses Implementer or Applier. The latter is 
named <oi-name>-inheritance-impl
diff --git a/python/samples/caps b/python/samples/caps
new file mode 100755
--- /dev/null
+++ b/python/samples/caps
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+
+import itertools
+
+from pyosaf.saAis import eSaAisErrorT
+
+from pyosaf.utils import SafException
+
+from pyosaf.utils.immoi.implementer import Implementer
+
+caps_class_name = "CapsSample"
+
+def handle_validate(all_instances, updated, created, deleted):
+
+    # Verify that upper and lower caps are correct in created objects
+    # and updated objects
+    for mo in itertools.chain(created, updated):
+
+        # Verify upper caps
+        if mo.upperCaps and not mo.upperCaps.isupper():
+            err_str = "ERROR: %s.upperCaps must be upper case (was %s)" % \
+                (mo.dn, mo.upperCaps)
+            raise SafException(eSaAisErrorT.SA_AIS_ERR_INVALID_PARAM, err_str)
+
+        # Verify lower caps
+        if mo.lowerCaps and not mo.lowerCaps.islower():
+            err_str = "ERROR: %s.lowerCaps must be lower case (was %s)" % \
+                      (mo.dn, mo.lowerCaps)
+            raise SafException(eSaAisErrorT.SA_AIS_ERR_INVALID_PARAM, err_str)
+
+
+if __name__ == "__main__":
+
+    # Create the implementer
+    classes = [caps_class_name]
+
+    caps_implementer = Implementer(on_validate=handle_validate, 
+                                   class_names=classes,
+                                   name="CapsImplementer")
+
+    # Start the infinite dispatch loop
+    caps_implementer.enter_dispatch_loop()
diff --git a/python/samples/caps-inheritance-impl 
b/python/samples/caps-inheritance-impl
new file mode 100755
--- /dev/null
+++ b/python/samples/caps-inheritance-impl
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+import itertools
+
+from pyosaf.saAis import eSaAisErrorT
+
+from pyosaf.utils import SafException
+
+from pyosaf.utils.immoi.implementer import Implementer
+
+caps_class_name = "CapsSample"
+
+class Caps(Implementer):
+    ''' The Caps implementer implements CapsSample and makes sure that
+        the upperCaps and lowerCaps consist only of uppercase characters
+        and lowercase characters respectively.'''
+
+    def __init__(self):
+        ''' Constructs the Caps instance '''
+        Implementer.__init__(self, class_names=[caps_class_name],
+                             name="CapsImplementer")
+
+    def on_validate(self, all_instances, to_update, to_create, to_delete):
+        ''' Validates that the rules for upperCaps and lowerCaps are kept '''
+
+        # Verify that upper and lower caps are correct in created objects
+        # and updated objects
+        for mo in itertools.chain(to_create, to_update):
+
+            # Verify upper caps
+            if mo.upperCaps and not mo.upperCaps.isupper():
+                err_str = "ERROR: %s.upperCaps must be upper case (was %s)" % \
+                    (mo.dn, mo.upperCaps)
+                raise SafException(eSaAisErrorT.SA_AIS_ERR_INVALID_PARAM, 
err_str)
+
+            # Verify lower caps
+            if mo.lowerCaps and not mo.lowerCaps.islower():
+                err_str = "ERROR: %s.lowerCaps must be lower case (was %s)" % \
+                          (mo.dn, mo.lowerCaps)
+                raise SafException(eSaAisErrorT.SA_AIS_ERR_INVALID_PARAM, 
err_str)
+
+
+if __name__ == "__main__":
+
+    # Create the implementer
+    caps_implementer = Caps()
+
+    # Start the infinite dispatch loop
+    caps_implementer.enter_dispatch_loop()
diff --git a/python/samples/imm-listener b/python/samples/imm-listener
new file mode 100755
--- /dev/null
+++ b/python/samples/imm-listener
@@ -0,0 +1,111 @@
+#!/usr/bin/env python
+
+import argparse
+import sys
+
+from pyosaf.saImm import eSaImmClassCategoryT
+
+from pyosaf.utils.immoi import get_available_classes_in_imm, get_class_category
+from pyosaf.utils.immoi.implementer import Applier
+
+
+def is_config_class(class_name):
+
+    category = get_class_category(class_name)
+
+    return category == eSaImmClassCategoryT.SA_IMM_CLASS_CONFIG
+
+
+def parse_class_names():
+
+    return args.classes
+
+def print_mo(mo):
+    ''' Prints an MO instance '''
+
+    print "    %s" % mo.dn
+
+    # Print attributes
+    for name, type_value_pair in mo.attrs.iteritems():
+        value = type_value_pair[1]
+
+        if len(value) == 1:
+            value = value[0]
+
+        print "        - %s: %s" % (name, value)
+
+def handle_apply(all_instances, updated, created, to_delete):
+
+    print
+    print '-' * 10 + " Configuration changed " + '-' * 10
+
+    # Handle creates
+    print "  Created objects"
+    for mo in created:
+        print_mo(mo)
+
+    # Handle deletes
+    print "  Deleted objects"
+    for mo in to_delete:
+        print "    %s" % mo
+
+    # Handle updates
+    print "  Updated objects"
+    for mo in updated:
+        print_mo(mo)
+        
+if __name__ == "__main__":
+
+    # Parse command line arguments
+    parser = argparse.ArgumentParser(
+        description='Listens to changes to objects of the given classes')
+    parser.add_argument('classes', type=str, nargs='*', 
+                        help='space-separated list of class names')
+    parser.add_argument('--all', help='listens to changes to all classes',
+                        dest='all', action='store_const', const=all, 
+                        default=False)
+
+    args = parser.parse_args()
+
+    classes = args.classes
+
+    listen_to_all = args.all
+
+    # Exit if no classes are passed
+    if not listen_to_all and (not classes or classes == []):
+        print "ERROR: Must specify classes to listen to or '--all'"
+        sys.exit(1)
+
+    # Sort out which classes to listen to
+    all_available_classes = get_available_classes_in_imm()
+    classes_to_listen_to = []
+
+    if listen_to_all:
+        print "INFO: Listening to changes to all configuration classes"
+
+        classes_to_listen_to = [c for c in all_available_classes if 
is_config_class(c)]
+
+    else:
+
+        # Validate classes
+        for class_name in classes:
+
+            if not class_name in all_available_classes:
+                print "WARNING: Ignoring %s. It does not exist in IMM" % 
class_name
+
+                continue
+
+            elif not is_config_class(class_name):
+                print "WARNING: Ignoring runtime class %s" % class_name
+
+                continue
+
+            classes_to_listen_to.append(class_name)
+
+    print "INFO: Listening for changes in %s" % ", ".join(classes_to_listen_to)
+
+    echo_applier = Applier(on_apply=handle_apply, 
+                           class_names=classes_to_listen_to,
+                           name="ImmListener")
+
+    echo_applier.enter_dispatch_loop()
diff --git a/python/samples/imm-listener-inheritance-impl 
b/python/samples/imm-listener-inheritance-impl
new file mode 100755
--- /dev/null
+++ b/python/samples/imm-listener-inheritance-impl
@@ -0,0 +1,158 @@
+#!/usr/bin/env python
+
+import argparse
+import sys
+
+from pyosaf.saAis import eSaAisErrorT
+
+from pyosaf.saImm import eSaImmClassCategoryT
+
+from pyosaf.utils.immoi import get_available_classes_in_imm, get_class_category
+from pyosaf.utils.immoi.implementer import Applier
+
+
+class ImmListener(Applier):
+    ''' This class listens to modifications to IMM and prints
+        them on STDOUT. 
+
+        It extends the Applier class and overrides the apply function.
+
+    '''
+
+    def __init__(self, class_names=[]):
+        ''' Creates a listener applier for the given class names '''
+        Applier.__init__(self, class_names, name='ImmListener')
+
+    def on_apply(self, instances, updated, created, deleted):
+        ''' Overrides the apply method in Applier to print
+            any modifications to configuration data in IMM
+        '''
+
+        print
+        print '-' * 10 + " Configuration changed " + '-' * 10
+
+        # Handle creates
+        print "  Created objects"
+        for mo in created:
+            self.print_mo(mo)
+
+        # Handle deletes
+        print "  Deleted objects"
+        for mo in deleted:
+            print "    %s" % mo
+
+        # Handle updates
+        print "  Updated objects"
+        for mo in updated:
+            self.print_mo(mo)
+
+    def on_create_added(self, class_name, parent, obj):
+        ''' Overrides on_create in Applier. This method is called each
+            time a create operation is added to a CCB.
+        '''
+
+        print
+        print
+        print '-' * 10  + " Create added to CCB " + '-' * 10
+        print
+        print "Class: %s" % class_name
+        print "Parent: %s" % parent
+        print
+        self.print_mo(obj)
+        print
+
+        return eSaAisErrorT.SA_AIS_OK
+
+    def on_delete_added(self, dn):
+        ''' Overrides on_delete in Applier. This method is called each
+            time a delete operations is added to a CCB.
+        '''
+
+        print
+        print
+        print '-' * 10 + " Delete added to CCB " + '-' * 10
+        print
+        print "    %s" % dn
+
+        return eSaAisErrorT.SA_AIS_OK
+
+    def print_mo(self, mo):
+        ''' Prints an MO instance '''
+
+        print "    %s" % mo.dn
+
+        # Print attributes
+        for name, type_value_pair in mo.attrs.iteritems():
+            value = type_value_pair[1]
+
+            if len(value) == 1:
+                value = value[0]
+
+            print "        - %s: %s" % (name, value)
+
+
+def is_config_class(class_name):
+    ''' Returns True if the given class is a configuration class,
+        otherwise False
+    '''
+
+    category = get_class_category(class_name)
+
+    return category == eSaImmClassCategoryT.SA_IMM_CLASS_CONFIG
+
+
+if __name__ == "__main__":
+
+    # Parse command line arguments
+    parser = argparse.ArgumentParser(
+        description='Listens to changes to objects of the given classes')
+    parser.add_argument('classes', type=str, nargs='*', 
+                        help='space-separated list of class names')
+    parser.add_argument('--all', help='listens to changes to all classes',
+                        dest='all', action='store_const', const=all, 
+                        default=False)
+
+    args = parser.parse_args()
+
+    classes = args.classes
+
+    listen_to_all = args.all
+
+    # Exit if no classes are passed
+    if not listen_to_all and (not classes or classes == []):
+        print "ERROR: Must specify classes to listen to or '--all'"
+        sys.exit(1)
+
+    # Sort out which classes to listen to
+    all_available_classes = get_available_classes_in_imm()
+    classes_to_listen_to = []
+
+    if listen_to_all:
+        print "INFO: Listening to changes to all configuration classes"
+
+        classes_to_listen_to = [c for c in all_available_classes \
+                                if is_config_class(c)]
+
+    else:
+
+        # Validate classes
+        for class_name in classes:
+
+            if not class_name in all_available_classes:
+                print "WARNING: Ignoring %s. It does not exist in IMM" % 
class_name
+
+                continue
+
+            elif not is_config_class(class_name):
+                print "WARNING: Ignoring runtime class %s" % class_name
+
+                continue
+
+            classes_to_listen_to.append(class_name)
+
+    print "INFO: Listening for changes in %s" % ", ".join(classes_to_listen_to)
+
+    imm_listener = ImmListener(classes_to_listen_to)
+
+    imm_listener.enter_dispatch_loop()
+
diff --git a/python/samples/immoi/samples/caps 
b/python/samples/immoi/samples/caps
deleted file mode 100755
--- a/python/samples/immoi/samples/caps
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env python
-
-import itertools
-
-from pyosaf.saAis import eSaAisErrorT
-
-from pyosaf.utils import SafException
-
-from pyosaf.utils.immoi.implementer import Implementer
-
-caps_class_name = "CapsSample"
-
-def handle_validate(all_instances, updated, created, deleted):
-
-    # Verify that upper and lower caps are correct in created objects
-    # and updated objects
-    for mo in itertools.chain(created, updated):
-
-        # Verify upper caps
-        if mo.upperCaps and not mo.upperCaps.isupper():
-            err_str = "ERROR: %s.upperCaps must be upper case (was %s)" % \
-                (mo.dn, mo.upperCaps)
-            raise SafException(eSaAisErrorT.SA_AIS_ERR_INVALID_PARAM, err_str)
-
-        # Verify lower caps
-        if mo.lowerCaps and not mo.lowerCaps.islower():
-            err_str = "ERROR: %s.lowerCaps must be lower case (was %s)" % \
-                      (mo.dn, mo.lowerCaps)
-            raise SafException(eSaAisErrorT.SA_AIS_ERR_INVALID_PARAM, err_str)
-
-
-if __name__ == "__main__":
-
-    # Create the implementer
-    classes = [caps_class_name]
-
-    caps_implementer = Implementer(on_validate=handle_validate, 
-                                   class_names=classes,
-                                   name="CapsImplementer")
-
-    # Start the infinite dispatch loop
-    caps_implementer.enter_dispatch_loop()
diff --git a/python/samples/immoi/samples/caps-inheritance-impl 
b/python/samples/immoi/samples/caps-inheritance-impl
deleted file mode 100755
--- a/python/samples/immoi/samples/caps-inheritance-impl
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/env python
-
-import itertools
-
-from pyosaf.saAis import eSaAisErrorT
-
-from pyosaf.utils import SafException
-
-from pyosaf.utils.immoi.implementer import Implementer
-
-caps_class_name = "CapsSample"
-
-class Caps(Implementer):
-    ''' The Caps implementer implements CapsSample and makes sure that
-        the upperCaps and lowerCaps consist only of uppercase characters
-        and lowercase characters respectively.'''
-
-    def __init__(self):
-        ''' Constructs the Caps instance '''
-        Implementer.__init__(self, class_names=[caps_class_name],
-                             name="CapsImplementer")
-
-    def on_validate(self, all_instances, to_update, to_create, to_delete):
-        ''' Validates that the rules for upperCaps and lowerCaps are kept '''
-
-        # Verify that upper and lower caps are correct in created objects
-        # and updated objects
-        for mo in itertools.chain(to_create, to_update):
-
-            # Verify upper caps
-            if mo.upperCaps and not mo.upperCaps.isupper():
-                err_str = "ERROR: %s.upperCaps must be upper case (was %s)" % \
-                    (mo.dn, mo.upperCaps)
-                raise SafException(eSaAisErrorT.SA_AIS_ERR_INVALID_PARAM, 
err_str)
-
-            # Verify lower caps
-            if mo.lowerCaps and not mo.lowerCaps.islower():
-                err_str = "ERROR: %s.lowerCaps must be lower case (was %s)" % \
-                          (mo.dn, mo.lowerCaps)
-                raise SafException(eSaAisErrorT.SA_AIS_ERR_INVALID_PARAM, 
err_str)
-
-
-if __name__ == "__main__":
-
-    # Create the implementer
-    caps_implementer = Caps()
-
-    # Start the infinite dispatch loop
-    caps_implementer.enter_dispatch_loop()
diff --git a/python/samples/immoi/samples/imm-listener 
b/python/samples/immoi/samples/imm-listener
deleted file mode 100755
--- a/python/samples/immoi/samples/imm-listener
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/usr/bin/env python
-
-import argparse
-import sys
-
-from pyosaf.saImm import eSaImmClassCategoryT
-
-from pyosaf.utils.immoi import get_available_classes_in_imm, get_class_category
-from pyosaf.utils.immoi.implementer import Applier
-
-
-def is_config_class(class_name):
-
-    category = get_class_category(class_name)
-
-    return category == eSaImmClassCategoryT.SA_IMM_CLASS_CONFIG
-
-
-def parse_class_names():
-
-    return args.classes
-
-def print_mo(mo):
-    ''' Prints an MO instance '''
-
-    print "    %s" % mo.dn
-
-    # Print attributes
-    for name, type_value_pair in mo.attrs.iteritems():
-        value = type_value_pair[1]
-
-        if len(value) == 1:
-            value = value[0]
-
-        print "        - %s: %s" % (name, value)
-
-def handle_apply(all_instances, updated, created, to_delete):
-
-    print
-    print '-' * 10 + " Configuration changed " + '-' * 10
-
-    # Handle creates
-    print "  Created objects"
-    for mo in created:
-        print_mo(mo)
-
-    # Handle deletes
-    print "  Deleted objects"
-    for mo in to_delete:
-        print "    %s" % mo
-
-    # Handle updates
-    print "  Updated objects"
-    for mo in updated:
-        print_mo(mo)
-        
-if __name__ == "__main__":
-
-    # Parse command line arguments
-    parser = argparse.ArgumentParser(
-        description='Listens to changes to objects of the given classes')
-    parser.add_argument('classes', type=str, nargs='*', 
-                        help='space-separated list of class names')
-    parser.add_argument('--all', help='listens to changes to all classes',
-                        dest='all', action='store_const', const=all, 
-                        default=False)
-
-    args = parser.parse_args()
-
-    classes = args.classes
-
-    listen_to_all = args.all
-
-    # Exit if no classes are passed
-    if not listen_to_all and (not classes or classes == []):
-        print "ERROR: Must specify classes to listen to or '--all'"
-        sys.exit(1)
-
-    # Sort out which classes to listen to
-    all_available_classes = get_available_classes_in_imm()
-    classes_to_listen_to = []
-
-    if listen_to_all:
-        print "INFO: Listening to changes to all configuration classes"
-
-        classes_to_listen_to = [c for c in all_available_classes if 
is_config_class(c)]
-
-    else:
-
-        # Validate classes
-        for class_name in classes:
-
-            if not class_name in all_available_classes:
-                print "WARNING: Ignoring %s. It does not exist in IMM" % 
class_name
-
-                continue
-
-            elif not is_config_class(class_name):
-                print "WARNING: Ignoring runtime class %s" % class_name
-
-                continue
-
-            classes_to_listen_to.append(class_name)
-
-    print "INFO: Listening for changes in %s" % ", ".join(classes_to_listen_to)
-
-    echo_applier = Applier(on_apply=handle_apply, 
-                           class_names=classes_to_listen_to,
-                           name="ImmListener")
-
-    echo_applier.enter_dispatch_loop()
diff --git a/python/samples/immoi/samples/imm-listener-inheritance-impl 
b/python/samples/immoi/samples/imm-listener-inheritance-impl
deleted file mode 100755
--- a/python/samples/immoi/samples/imm-listener-inheritance-impl
+++ /dev/null
@@ -1,158 +0,0 @@
-#!/usr/bin/env python
-
-import argparse
-import sys
-
-from pyosaf.saAis import eSaAisErrorT
-
-from pyosaf.saImm import eSaImmClassCategoryT
-
-from pyosaf.utils.immoi import get_available_classes_in_imm, get_class_category
-from pyosaf.utils.immoi.implementer import Applier
-
-
-class ImmListener(Applier):
-    ''' This class listens to modifications to IMM and prints
-        them on STDOUT. 
-
-        It extends the Applier class and overrides the apply function.
-
-    '''
-
-    def __init__(self, class_names=[]):
-        ''' Creates a listener applier for the given class names '''
-        Applier.__init__(self, class_names, name='ImmListener')
-
-    def on_apply(self, instances, updated, created, deleted):
-        ''' Overrides the apply method in Applier to print
-            any modifications to configuration data in IMM
-        '''
-
-        print
-        print '-' * 10 + " Configuration changed " + '-' * 10
-
-        # Handle creates
-        print "  Created objects"
-        for mo in created:
-            self.print_mo(mo)
-
-        # Handle deletes
-        print "  Deleted objects"
-        for mo in deleted:
-            print "    %s" % mo
-
-        # Handle updates
-        print "  Updated objects"
-        for mo in updated:
-            self.print_mo(mo)
-
-    def on_create_added(self, class_name, parent, obj):
-        ''' Overrides on_create in Applier. This method is called each
-            time a create operation is added to a CCB.
-        '''
-
-        print
-        print
-        print '-' * 10  + " Create added to CCB " + '-' * 10
-        print
-        print "Class: %s" % class_name
-        print "Parent: %s" % parent
-        print
-        self.print_mo(obj)
-        print
-
-        return eSaAisErrorT.SA_AIS_OK
-
-    def on_delete_added(self, dn):
-        ''' Overrides on_delete in Applier. This method is called each
-            time a delete operations is added to a CCB.
-        '''
-
-        print
-        print
-        print '-' * 10 + " Delete added to CCB " + '-' * 10
-        print
-        print "    %s" % dn
-
-        return eSaAisErrorT.SA_AIS_OK
-
-    def print_mo(self, mo):
-        ''' Prints an MO instance '''
-
-        print "    %s" % mo.dn
-
-        # Print attributes
-        for name, type_value_pair in mo.attrs.iteritems():
-            value = type_value_pair[1]
-
-            if len(value) == 1:
-                value = value[0]
-
-            print "        - %s: %s" % (name, value)
-
-
-def is_config_class(class_name):
-    ''' Returns True if the given class is a configuration class,
-        otherwise False
-    '''
-
-    category = get_class_category(class_name)
-
-    return category == eSaImmClassCategoryT.SA_IMM_CLASS_CONFIG
-
-
-if __name__ == "__main__":
-
-    # Parse command line arguments
-    parser = argparse.ArgumentParser(
-        description='Listens to changes to objects of the given classes')
-    parser.add_argument('classes', type=str, nargs='*', 
-                        help='space-separated list of class names')
-    parser.add_argument('--all', help='listens to changes to all classes',
-                        dest='all', action='store_const', const=all, 
-                        default=False)
-
-    args = parser.parse_args()
-
-    classes = args.classes
-
-    listen_to_all = args.all
-
-    # Exit if no classes are passed
-    if not listen_to_all and (not classes or classes == []):
-        print "ERROR: Must specify classes to listen to or '--all'"
-        sys.exit(1)
-
-    # Sort out which classes to listen to
-    all_available_classes = get_available_classes_in_imm()
-    classes_to_listen_to = []
-
-    if listen_to_all:
-        print "INFO: Listening to changes to all configuration classes"
-
-        classes_to_listen_to = [c for c in all_available_classes \
-                                if is_config_class(c)]
-
-    else:
-
-        # Validate classes
-        for class_name in classes:
-
-            if not class_name in all_available_classes:
-                print "WARNING: Ignoring %s. It does not exist in IMM" % 
class_name
-
-                continue
-
-            elif not is_config_class(class_name):
-                print "WARNING: Ignoring runtime class %s" % class_name
-
-                continue
-
-            classes_to_listen_to.append(class_name)
-
-    print "INFO: Listening for changes in %s" % ", ".join(classes_to_listen_to)
-
-    imm_listener = ImmListener(classes_to_listen_to)
-
-    imm_listener.enter_dispatch_loop()
-
diff --git a/python/samples/immoi/samples/ping-pong 
b/python/samples/immoi/samples/ping-pong
deleted file mode 100755
--- a/python/samples/immoi/samples/ping-pong
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/env python
-
-import select
-
-from pyosaf.saAis import eSaAisErrorT
-
-from pyosaf.utils import immom
-from pyosaf.utils.immoi.implementer import Implementer, AdminOperationFunction
-from pyosaf.utils.immom.object import ImmObject
-from pyosaf.utils.immom.ccb import Ccb
-
-class_name = "PingPong"
-dn         = "pingPongId=1"
-
-
-def ping(dn, arguments):
-    print
-    print
-    print "Pong!"
-    print
-
-    print "INFO: I am %s, received arguments %s" % (dn, arguments)
-
-    return eSaAisErrorT.SA_AIS_OK
-
-
-def pong(dn, arguments):
-    print 
-    print
-    print "Ping!"
-    print
-
-    print "INFO: I am %s, received arguments %s" % (dn, arguments)
-
-    return eSaAisErrorT.SA_AIS_OK
-
-
-if __name__ == '__main__':
-
-    # Create the ping-pong instance if it doesn't exist
-    if not immom.get(dn):
-
-        with Ccb(flags=None) as ccb:
-            obj = ImmObject(class_name=class_name, dn=dn)
-
-            obj.pingPongId  = "pingPongId=1"
-
-            ccb.create(obj)
-
-    # Create the implementer instance
-    operations = [AdminOperationFunction(class_name, 0, ping),
-                  AdminOperationFunction(class_name, 1, pong)]
-
-    implementer = Implementer(class_names=[class_name])
-
-    implementer.set_admin_operations(operations)
-
-    # Start dispatch and time update loop
-    implementer.enter_dispatch_loop()
diff --git a/python/samples/immoi/samples/ping-pong-inheritance-impl 
b/python/samples/immoi/samples/ping-pong-inheritance-impl
deleted file mode 100755
--- a/python/samples/immoi/samples/ping-pong-inheritance-impl
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/bin/env python
-
-import select
-
-from pyosaf.saAis import eSaAisErrorT
-
-from pyosaf.utils import immom
-from pyosaf.utils.immoi.implementer import Implementer, AdminOperation
-from pyosaf.utils.immom.object import ImmObject
-from pyosaf.utils.immom.ccb import Ccb
-
-class_name = "PingPong"
-dn         = "pingPongId=1"
-
-class PingPong(Implementer):
-
-    def __init__(self):
-        Implementer.__init__(self, class_names=[class_name])
-
-    @AdminOperation(class_name, 0)
-    def ping(self, dn, arguments):
-        print
-        print
-        print "Pong!"
-        print
-        print "INFO: I am %s, received arguments %s" % (dn, arguments)
-
-    @AdminOperation(class_name, 1)
-    def pong(self, dn, arguments):
-        print 
-        print
-        print "Ping!"
-        print
-        print "INFO: I am %s, received arguments %s" % (dn, arguments)
-
-
-if __name__ == '__main__':
-
-    # Create the ping-pong instance if it doesn't exist
-    if not immom.get(dn):
-
-        with Ccb(flags=None) as ccb:
-            obj = ImmObject(class_name=class_name, dn=dn)
-
-            obj.pingPongId  = "pingPongId=1"
-
-            ccb.create(obj)
-
-    # Create the implementer instance
-    implementer = PingPong()
-
-    # Start dispatch and time update loop
-    implementer.enter_dispatch_loop()
diff --git a/python/samples/immoi/samples/time-reporter 
b/python/samples/immoi/samples/time-reporter
deleted file mode 100755
--- a/python/samples/immoi/samples/time-reporter
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/usr/bin/env python
-
-import select
-import datetime
-
-from pyosaf.utils import immom, immoi
-from pyosaf.utils.immoi.implementer import Implementer
-from pyosaf.utils.immom.object import ImmObject
-
-class_name = "TimeSample"
-dn         = "timeId=1"
-timeout    = 1
-
-def get_time():
-    now = datetime.datetime.now()
-
-    return (now.hour, now.minute, now.second)
-
-def select_loop(implementer):
-
-    # Get selection object for the implementer
-    selection_object = implementer.get_selection_object()
-
-    # Wait for next OI event or one second timeout
-    inputs  = [selection_object]
-    outputs = []
-
-    while inputs:
-
-        readable, writable, exceptional = \
-        select.select(inputs, outputs, inputs, timeout)
-
-        if selection_object in readable:
-            implementer.dispatch()
-        else:
-
-            # Update the time
-            (hours, minutes, seconds) = get_time()
-
-            attributes = {'hours'   : hours,
-                          'minutes' : minutes,
-                          'seconds' : seconds}
-
-            implementer.update_runtime_attributes(dn, attributes)
-
-if __name__ == '__main__':
-
-    # Create the implementer instance
-    time_implementer = Implementer(name="TimeReporter")
-
-    # Get the current time
-    (hours, minutes, seconds) = get_time()
-
-    # Create the time instance if it doesn't exist
-    if not immoi.get_object_no_runtime(dn):
-
-        obj = ImmObject(class_name=class_name, dn=dn)
-
-        obj.hours   = hours
-        obj.minutes = minutes
-        obj.seconds = seconds
-        obj.timeId  = "timeId=1"
-
-        time_implementer.create(obj)
-
-    # Start dispatch and time update loop
-    select_loop(time_implementer)
diff --git a/python/samples/immoi/samples/time-reporter-inheritance-impl 
b/python/samples/immoi/samples/time-reporter-inheritance-impl
deleted file mode 100755
--- a/python/samples/immoi/samples/time-reporter-inheritance-impl
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/env python
-
-import select
-import datetime
-
-from pyosaf.utils import immom, immoi
-from pyosaf.utils.immoi.implementer import Implementer
-from pyosaf.utils.immom.object import ImmObject
-
-class_name = "TimeSample"
-dn         = "timeId=1"
-timeout    = 1
-
-class TimeReporter(Implementer):
-    ''' This implementer creates a runtime object and updates it with
-        the current time according to the configured timeout (in seconds)'''
-
-    def __init__(self, timeout=1, time_id=1):
-        ''' Initializes this time reporter instance '''
-
-        Implementer.__init__(self, name="TimeReporter")
-
-        self.timeout = timeout
-        self.time_id = time_id
-
-    def create_time_instance(self):
-
-        # Create the time instance if it doesn't exist
-        dn = "timeId=%s" % self.time_id
-
-        if not immoi.get_object_no_runtime(dn):
-
-            now = datetime.datetime.now()
-
-            obj = ImmObject(class_name=class_name, dn=dn)
-
-            obj.hours   = now.hour
-            obj.minutes = now.minute
-            obj.seconds = now.second
-            obj.timeId  = "timeId=%" % self.time_id
-
-            time_implementer.create(obj)
-
-    def enter_dispatch_loop(self):
-        ''' 
-            Loops continuously and dispatches callbacks or updates the 
-            current time
-        '''
-
-        # Get selection object for the implementer
-        selection_object = self.get_selection_object()
-
-        # Wait for next OI event or one second timeout
-        inputs  = [selection_object]
-        outputs = []
-
-        while inputs:
-
-            readable, writable, exceptional = \
-            select.select(inputs, outputs, inputs, self.timeout)
-
-            if selection_object in readable:
-                self.dispatch()
-            else:
-
-                # Update the time
-                now = datetime.datetime.now()
-
-                attributes = {'hours'   : now.hour,
-                              'minutes' : now.minute,
-                              'seconds' : now.second}
-
-                self.update_runtime_attributes(dn, attributes)
-
-if __name__ == '__main__':
-
-    # Create the implementer instance
-    time_implementer = TimeReporter(time_id=1)
-
-
-    # Start dispatch and time update loop
-    time_implementer.enter_dispatch_loop()
diff --git a/python/samples/immoi/samples/tones 
b/python/samples/immoi/samples/tones
deleted file mode 100755
--- a/python/samples/immoi/samples/tones
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env python
-
-from pyosaf.utils.immoi import implementer
-
-tone_class_names = ["Do", "Re", "Mi", "Fa", "So", "La", "Ti"]
-
-        
-if __name__ == "__main__":
-
-    # Set up containment constraints
-    constraints = implementer.Constraints()
-
-    constraints.add_allowed_containment('Do', 'Re', upper=1)
-    constraints.add_allowed_containment('Re', 'Mi', upper=1)
-    constraints.add_allowed_containment('Mi', 'Fa', upper=1)
-    constraints.add_allowed_containment('Fa', 'So', upper=1)
-    constraints.add_allowed_containment('So', 'La', upper=1)
-    constraints.add_allowed_containment('La', 'Ti', upper=1)
-
-    # Create the implementer
-    tones_implementer = implementer.Implementer(class_names=tone_class_names,
-                                                name="TonesImplementer")
-
-    tones_implementer.set_constraints(constraints)
-
-    # Start the infinite dispatch loop
-    tones_implementer.enter_dispatch_loop()
diff --git a/python/samples/immoi/samples/tones-inheritance-impl 
b/python/samples/immoi/samples/tones-inheritance-impl
deleted file mode 100755
--- a/python/samples/immoi/samples/tones-inheritance-impl
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python
-
-from pyosaf.utils.immoi.implementer import Implementer, Constraints
-
-class Tones(Implementer):
-
-    def __init__(self):
-        tone_class_names = ["Do", "Re", "Mi", "Fa", "So", "La", "Ti"]
-
-        Implementer.__init__(self, class_names=tone_class_names,
-                             name="TonesImplementer")
-
-        # Set up containment constraints
-        constraints = Constraints()
-
-        constraints.add_allowed_containment('Do', 'Re', upper=1)
-        constraints.add_allowed_containment('Re', 'Mi', upper=1)
-        constraints.add_allowed_containment('Mi', 'Fa', upper=1)
-        constraints.add_allowed_containment('Fa', 'So', upper=1)
-        constraints.add_allowed_containment('So', 'La', upper=1)
-        constraints.add_allowed_containment('La', 'Ti', upper=1)
-
-        self.set_constraints(constraints)
-
-        
-if __name__ == "__main__":
-
-    # Create the implementer
-    tones_implementer = Tones()
-
-    # Start the infinite dispatch loop
-    tones_implementer.enter_dispatch_loop()
diff --git a/python/samples/immoi/samples/users 
b/python/samples/immoi/samples/users
deleted file mode 100755
--- a/python/samples/immoi/samples/users
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env python
-
-from pyosaf import saAis
-from pyosaf.utils import immom, immoi, SafException
-from pyosaf.utils.immom.object import ImmObject
-from pyosaf.utils.immoi.implementer import Implementer
-
-import psutil
-
-class_name='UsersSampleClass'
-
-def on_attribute_update(*args):
-    return list(set(map(lambda x: x.name, psutil.get_users())))
-
-if __name__ == '__main__':
-    
-    users_implementer = Implementer(on_runtime_values_get=on_attribute_update,
-                                    name='UsersImplementer')
-
-    try:
-        obj = ImmObject(class_name=class_name, dn='usersId=1')
-
-        obj.usersId = 'usersId=1'
-
-        users_implementer.create(obj)
-    except SafException as err:
-        if not err.value == saAis.eSaAisErrorT.SA_AIS_ERR_EXIST:
-            raise err
-        
-    users_implementer.enter_dispatch_loop()
diff --git a/python/samples/immoi/samples/users-inheritance-impl 
b/python/samples/immoi/samples/users-inheritance-impl
deleted file mode 100755
--- a/python/samples/immoi/samples/users-inheritance-impl
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env python
-
-from pyosaf import saAis
-from pyosaf.utils import immom, immoi, SafException
-from pyosaf.utils.immom.object import ImmObject
-from pyosaf.utils.immoi.implementer import Implementer
-
-import psutil
-
-class_name='UsersSampleClass'
-
-class UsersImplementer(Implementer):
-
-    def __init__(self):
-        Implementer.__init__(self, name='UsersImplementer')
-
-    def on_runtime_values_get(self, name, class_name, attribute):
-        return list(set(map(lambda x: x.name, psutil.get_users())))
-
-if __name__ == '__main__':
-    
-    users_implementer = UsersImplementer()
-
-    try:
-        obj = ImmObject(class_name=class_name, dn='usersId=1')
-
-        obj.usersId = 'usersId=1'
-
-        users_implementer.create(obj)
-    except SafException as err:
-        if not err.value == saAis.eSaAisErrorT.SA_AIS_ERR_EXIST:
-            raise err
-        
-    users_implementer.enter_dispatch_loop()
diff --git a/python/samples/ping-pong b/python/samples/ping-pong
new file mode 100755
--- /dev/null
+++ b/python/samples/ping-pong
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+
+import select
+
+from pyosaf.saAis import eSaAisErrorT
+
+from pyosaf.utils import immom
+from pyosaf.utils.immoi.implementer import Implementer, AdminOperationFunction
+from pyosaf.utils.immom.object import ImmObject
+from pyosaf.utils.immom.ccb import Ccb
+
+class_name = "PingPong"
+dn         = "pingPongId=1"
+
+
+def ping(dn, arguments):
+    print
+    print
+    print "Pong!"
+    print
+
+    print "INFO: I am %s, received arguments %s" % (dn, arguments)
+
+    return eSaAisErrorT.SA_AIS_OK
+
+
+def pong(dn, arguments):
+    print 
+    print
+    print "Ping!"
+    print
+
+    print "INFO: I am %s, received arguments %s" % (dn, arguments)
+
+    return eSaAisErrorT.SA_AIS_OK
+
+
+if __name__ == '__main__':
+
+    # Create the ping-pong instance if it doesn't exist
+    if not immom.get(dn):
+
+        with Ccb(flags=None) as ccb:
+            obj = ImmObject(class_name=class_name, dn=dn)
+
+            obj.pingPongId  = "pingPongId=1"
+
+            ccb.create(obj)
+
+    # Create the implementer instance
+    operations = [AdminOperationFunction(class_name, 0, ping),
+                  AdminOperationFunction(class_name, 1, pong)]
+
+    implementer = Implementer(class_names=[class_name])
+
+    implementer.set_admin_operations(operations)
+
+    # Start dispatch and time update loop
+    implementer.enter_dispatch_loop()
diff --git a/python/samples/ping-pong-inheritance-impl 
b/python/samples/ping-pong-inheritance-impl
new file mode 100755
--- /dev/null
+++ b/python/samples/ping-pong-inheritance-impl
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+
+import select
+
+from pyosaf.saAis import eSaAisErrorT
+
+from pyosaf.utils import immom
+from pyosaf.utils.immoi.implementer import Implementer, AdminOperation
+from pyosaf.utils.immom.object import ImmObject
+from pyosaf.utils.immom.ccb import Ccb
+
+class_name = "PingPong"
+dn         = "pingPongId=1"
+
+class PingPong(Implementer):
+
+    def __init__(self):
+        Implementer.__init__(self, class_names=[class_name])
+
+    @AdminOperation(class_name, 0)
+    def ping(self, dn, arguments):
+        print
+        print
+        print "Pong!"
+        print
+        print "INFO: I am %s, received arguments %s" % (dn, arguments)
+
+    @AdminOperation(class_name, 1)
+    def pong(self, dn, arguments):
+        print 
+        print
+        print "Ping!"
+        print
+        print "INFO: I am %s, received arguments %s" % (dn, arguments)
+
+
+if __name__ == '__main__':
+
+    # Create the ping-pong instance if it doesn't exist
+    if not immom.get(dn):
+
+        with Ccb(flags=None) as ccb:
+            obj = ImmObject(class_name=class_name, dn=dn)
+
+            obj.pingPongId  = "pingPongId=1"
+
+            ccb.create(obj)
+
+    # Create the implementer instance
+    implementer = PingPong()
+
+    # Start dispatch and time update loop
+    implementer.enter_dispatch_loop()
diff --git a/python/samples/time-reporter b/python/samples/time-reporter
new file mode 100755
--- /dev/null
+++ b/python/samples/time-reporter
@@ -0,0 +1,67 @@
+#!/usr/bin/env python
+
+import select
+import datetime
+
+from pyosaf.utils import immom, immoi
+from pyosaf.utils.immoi.implementer import Implementer
+from pyosaf.utils.immom.object import ImmObject
+
+class_name = "TimeSample"
+dn         = "timeId=1"
+timeout    = 1
+
+def get_time():
+    now = datetime.datetime.now()
+
+    return (now.hour, now.minute, now.second)
+
+def select_loop(implementer):
+
+    # Get selection object for the implementer
+    selection_object = implementer.get_selection_object()
+
+    # Wait for next OI event or one second timeout
+    inputs  = [selection_object]
+    outputs = []
+
+    while inputs:
+
+        readable, writable, exceptional = \
+        select.select(inputs, outputs, inputs, timeout)
+
+        if selection_object in readable:
+            implementer.dispatch()
+        else:
+
+            # Update the time
+            (hours, minutes, seconds) = get_time()
+
+            attributes = {'hours'   : hours,
+                          'minutes' : minutes,
+                          'seconds' : seconds}
+
+            implementer.update_runtime_attributes(dn, attributes)
+
+if __name__ == '__main__':
+
+    # Create the implementer instance
+    time_implementer = Implementer(name="TimeReporter")
+
+    # Get the current time
+    (hours, minutes, seconds) = get_time()
+
+    # Create the time instance if it doesn't exist
+    if not immoi.get_object_no_runtime(dn):
+
+        obj = ImmObject(class_name=class_name, dn=dn)
+
+        obj.hours   = hours
+        obj.minutes = minutes
+        obj.seconds = seconds
+        obj.timeId  = "timeId=1"
+
+        time_implementer.create(obj)
+
+    # Start dispatch and time update loop
+    select_loop(time_implementer)
diff --git a/python/samples/time-reporter-inheritance-impl 
b/python/samples/time-reporter-inheritance-impl
new file mode 100755
--- /dev/null
+++ b/python/samples/time-reporter-inheritance-impl
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+
+import select
+import datetime
+
+from pyosaf.utils import immom, immoi
+from pyosaf.utils.immoi.implementer import Implementer
+from pyosaf.utils.immom.object import ImmObject
+
+class_name = "TimeSample"
+dn         = "timeId=1"
+timeout    = 1
+
+class TimeReporter(Implementer):
+    ''' This implementer creates a runtime object and updates it with
+        the current time according to the configured timeout (in seconds)'''
+
+    def __init__(self, timeout=1, time_id=1):
+        ''' Initializes this time reporter instance '''
+
+        Implementer.__init__(self, name="TimeReporter")
+
+        self.timeout = timeout
+        self.time_id = time_id
+
+    def create_time_instance(self):
+
+        # Create the time instance if it doesn't exist
+        dn = "timeId=%s" % self.time_id
+
+        if not immoi.get_object_no_runtime(dn):
+
+            now = datetime.datetime.now()
+
+            obj = ImmObject(class_name=class_name, dn=dn)
+
+            obj.hours   = now.hour
+            obj.minutes = now.minute
+            obj.seconds = now.second
+            obj.timeId  = "timeId=%" % self.time_id
+
+            time_implementer.create(obj)
+
+    def enter_dispatch_loop(self):
+        ''' 
+            Loops continuously and dispatches callbacks or updates the 
+            current time
+        '''
+
+        # Get selection object for the implementer
+        selection_object = self.get_selection_object()
+
+        # Wait for next OI event or one second timeout
+        inputs  = [selection_object]
+        outputs = []
+
+        while inputs:
+
+            readable, writable, exceptional = \
+            select.select(inputs, outputs, inputs, self.timeout)
+
+            if selection_object in readable:
+                self.dispatch()
+            else:
+
+                # Update the time
+                now = datetime.datetime.now()
+
+                attributes = {'hours'   : now.hour,
+                              'minutes' : now.minute,
+                              'seconds' : now.second}
+
+                self.update_runtime_attributes(dn, attributes)
+
+if __name__ == '__main__':
+
+    # Create the implementer instance
+    time_implementer = TimeReporter(time_id=1)
+
+
+    # Start dispatch and time update loop
+    time_implementer.enter_dispatch_loop()
diff --git a/python/samples/tones b/python/samples/tones
new file mode 100755
--- /dev/null
+++ b/python/samples/tones
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+
+from pyosaf.utils.immoi import implementer
+
+tone_class_names = ["Do", "Re", "Mi", "Fa", "So", "La", "Ti"]
+
+        
+if __name__ == "__main__":
+
+    # Set up containment constraints
+    constraints = implementer.Constraints()
+
+    constraints.add_allowed_containment('Do', 'Re', upper=1)
+    constraints.add_allowed_containment('Re', 'Mi', upper=1)
+    constraints.add_allowed_containment('Mi', 'Fa', upper=1)
+    constraints.add_allowed_containment('Fa', 'So', upper=1)
+    constraints.add_allowed_containment('So', 'La', upper=1)
+    constraints.add_allowed_containment('La', 'Ti', upper=1)
+
+    # Create the implementer
+    tones_implementer = implementer.Implementer(class_names=tone_class_names,
+                                                name="TonesImplementer")
+
+    tones_implementer.set_constraints(constraints)
+
+    # Start the infinite dispatch loop
+    tones_implementer.enter_dispatch_loop()
diff --git a/python/samples/tones-inheritance-impl 
b/python/samples/tones-inheritance-impl
new file mode 100755
--- /dev/null
+++ b/python/samples/tones-inheritance-impl
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+
+from pyosaf.utils.immoi.implementer import Implementer, Constraints
+
+class Tones(Implementer):
+
+    def __init__(self):
+        tone_class_names = ["Do", "Re", "Mi", "Fa", "So", "La", "Ti"]
+
+        Implementer.__init__(self, class_names=tone_class_names,
+                             name="TonesImplementer")
+
+        # Set up containment constraints
+        constraints = Constraints()
+
+        constraints.add_allowed_containment('Do', 'Re', upper=1)
+        constraints.add_allowed_containment('Re', 'Mi', upper=1)
+        constraints.add_allowed_containment('Mi', 'Fa', upper=1)
+        constraints.add_allowed_containment('Fa', 'So', upper=1)
+        constraints.add_allowed_containment('So', 'La', upper=1)
+        constraints.add_allowed_containment('La', 'Ti', upper=1)
+
+        self.set_constraints(constraints)
+
+        
+if __name__ == "__main__":
+
+    # Create the implementer
+    tones_implementer = Tones()
+
+    # Start the infinite dispatch loop
+    tones_implementer.enter_dispatch_loop()
diff --git a/python/samples/users b/python/samples/users
new file mode 100755
--- /dev/null
+++ b/python/samples/users
@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+
+from pyosaf import saAis
+from pyosaf.utils import immom, immoi, SafException
+from pyosaf.utils.immom.object import ImmObject
+from pyosaf.utils.immoi.implementer import Implementer
+
+import psutil
+
+class_name='UsersSampleClass'
+
+def on_attribute_update(*args):
+    return list(set(map(lambda x: x.name, psutil.get_users())))
+
+if __name__ == '__main__':
+    
+    users_implementer = Implementer(on_runtime_values_get=on_attribute_update,
+                                    name='UsersImplementer')
+
+    try:
+        obj = ImmObject(class_name=class_name, dn='usersId=1')
+
+        obj.usersId = 'usersId=1'
+
+        users_implementer.create(obj)
+    except SafException as err:
+        if not err.value == saAis.eSaAisErrorT.SA_AIS_ERR_EXIST:
+            raise err
+        
+    users_implementer.enter_dispatch_loop()
diff --git a/python/samples/users-inheritance-impl 
b/python/samples/users-inheritance-impl
new file mode 100755
--- /dev/null
+++ b/python/samples/users-inheritance-impl
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+
+from pyosaf import saAis
+from pyosaf.utils import immom, immoi, SafException
+from pyosaf.utils.immom.object import ImmObject
+from pyosaf.utils.immoi.implementer import Implementer
+
+import psutil
+
+class_name='UsersSampleClass'
+
+class UsersImplementer(Implementer):
+
+    def __init__(self):
+        Implementer.__init__(self, name='UsersImplementer')
+
+    def on_runtime_values_get(self, name, class_name, attribute):
+        return list(set(map(lambda x: x.name, psutil.get_users())))
+
+if __name__ == '__main__':
+    
+    users_implementer = UsersImplementer()
+
+    try:
+        obj = ImmObject(class_name=class_name, dn='usersId=1')
+
+        obj.usersId = 'usersId=1'
+
+        users_implementer.create(obj)
+    except SafException as err:
+        if not err.value == saAis.eSaAisErrorT.SA_AIS_ERR_EXIST:
+            raise err
+        
+    users_implementer.enter_dispatch_loop()

------------------------------------------------------------------------------
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to