Menu

#1406 pyosaf: Higher leve/pythonic bindings for the IMM OI API are missing

4.7.FC
fixed
None
enhancement
pyosaf
-
major
2015-09-29
2015-07-07
No

For the IMM OM API there are higher level python bindings that make it much easier to use compared with the 1-to-1 python bindings. There is for example an InstanceIterator class that iterates through instances for a given class, Ccb class for transactions and immom.get() to retrieve a single object.

The IMM OI API only has the 1-to-1 mappings. This makes it hard to write an OI as all the wrapping of python types to C and back has to be done by each user. OpenSAF should have an abstracted OI python mapping that hides the C (un)marshalling and caching and re-construction of CCB operations.

Related

Tickets: #1406
Wiki: NEWS-4.7.0

Discussion

  • Anders Bjornerstedt

    • Version: opensaf-staging -->
     
  • Johan Mårtensson

    • status: unassigned --> assigned
    • assigned_to: Johan Mårtensson
    • Version: --> future
     
  • Johan Mårtensson

    There are a set of requirements a high-level API for OI should fulfill:

    • Caching of CCBs and re-construction of the complete transaction should be done by the framework, not the user code
    • Marshalling from Python code to C should be hidden and done by the framework
    • It must be possible to build a "full" OI, that gets callbacks on each operation, the completed transaction, and a call to apply the transaction
    • It must be possible to build an applier that can run in parallel with a full OI
    • There should only need to be "user code" for the functionality the user wants to have. E.g., if the user doesn't want to get callbacks for each individual CCB operation, it shouldn't need to write placeholder functions that do nothing
    • It should be possible flexible so the user can choose to either:
      • Let the framework code handle the full dispatch loop and select handling
      • Let the user integrate the OI with its own dispatch loop and select handling
     
  • Johan Mårtensson

    • There should also be a convenience method to create RT objects, similar to create in ccb.py.
     
  • Johan Mårtensson

    Here is an example of how a (working) prototype program could look like that's using higher level bindings.

    #!/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.value == eSaImmClassCategoryT.SA_IMM_CLASS_CONFIG
    
    
    def parse_class_names():
    
        return args.classes
    
    def print_mo(mo):
        print "    %s (%s)" % (mo.dn, mo.SaImmAttrClassName)
    
        # Print attributes
        for name in mo.attrs.keys():
            print "        %s: %s" % (name, mo.attrs[name][1])
    
        print
    
    def handle_apply(all_instances, to_update, to_create, to_delete):
    
        print
        print '-' * 10 + " Configuration changed " + '-' * 10
    
        # Handle creates
        print "  Created objects"
        for mo in to_create:
            print_mo(mo)
    
        # Handle deletes
        print "  Deleted objects"
        for mo in to_delete:
            print_mo(mo)
    
        # Handle updates
        print "  Updated objects"
        for mo in to_update:
            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)
    
        echo_applier.enter_dispatch_loop()
    
     
  • Anders Bjornerstedt

    • Version: future -->
     
  • Srikanth R

    Srikanth R - 2015-08-27
    • status: assigned --> review
    • Milestone: future --> 4.7.FC
     
  • Srikanth R

    Srikanth R - 2015-09-29
    • status: review --> fixed
     

Log in to post a comment.

MongoDB Logo MongoDB