RFC: Script development

Radek Novacek rnovacek at redhat.com
Fri Jun 21 13:00:07 UTC 2013


Hi,

On Wed 12 of Jun 2013 12:20:14 Jan Synacek wrote:
> On 06/11/2013 10:52 PM, Jan Safranek wrote:
> > Hi,
> 
> Hello!
> 
> > I've been talking to Stephen Gallagher how to proceed with client script
> > development in lmishell. The goal is to provide high-level functionality
> > to manage remote systems without complete knowledge of the CIM API.
> > 
> > We agreed that:
> > 
> > - we should provide python modules with high-level functions
> > 
> > (we were thinking about nice classes, e.g. VolumeGroup with methods to
> > extend/destroy/examine a volume group, but it would end up in
> > duplicating the API we already have. We also assume that our users are
> > not familiar with OOP).
> 
> Define "our users". Are they admins that will use the scriptons from python
> scripts? If yes, I think that degrading the CIM API from OOP to pure
> procedural just doesn't sound right. Or maybe I'm just misunderstanding
> something here.

I agree, OOP is not something evil we want to hide from our users. It might be 
sometimes more convenient to use object-based api than procedural paradigm. 
Also we should first agreed how the api should look, set some common functions 
and make all of the scripton as similar as possible.

Compare following examples of service scripton API (with questions we should 
agree upon as comments):

1) procedural:

def get_services(nm=None):
    """ Returns list of services """
    # How? as list of LMI_Service instances? or as list of service names?

def service_start(service, nm=None):
    """ Start given service """
    # What is service parameter? String with service name? LMI_Service 
instance? Both?

def service_status(service, nm=None):
    """ Get status of given service """
    # What to return? Some enum values?

2) object-based:

class Service(object):
	def __init__(self, name, nm=None):
        """ Get service by given name """

    def start(self):
        """ Start the service """

    def status(self):
        """ Get status of the service """
        # What to return? Some enum values?

    @classmethod
    def get_all(cls, nm=None):
        """ Get instances of all services on the system """
        # Or have this rather a top level function?


This is just an example how I imagine that the scripton API for services might 
look. I personally like the object-based API more, but I'm not targeted user 
:) Maybe we could prototype both and show it to some potential users 
(sysadmins).

But we should definitely agree upon how the API should look for all of the 
scriptons. We really don't want to have just another set of different APIs 
with different look-and-feel.

> > - these python functions try to hide the object model - we assume that
> > administrators won't remember association names and won't use e.g.
> > vg.associators(AssocClass="LMI_VGAssociatedComponentExtent") to get list
> > of physical volumes of a vg. We want nice vg_get_pvs(vg) function. We
> > will expose CIM classes and properties though.
> > 
> > - these python functions are synchronous, i.e. they do stuff and return
> > once the stuff is finished. They can do stuff in parallel inside (e.g.
> > format multiple devices simultaneously) but from outside perspective,
> > the stuff is completed once the function returns.
> 
> What about leaving an option for functions that are asynchronous to run
> asynchronously? Or create both async and sync version of such functions.
> Because, again, forcing something that can be run asynchronously into a
> synchronous mode is degrading what we already have, needlessly. IMO we
> shouldn't make things more simple than simple.

Yes, I think we should have the possibility to let the longterm methods to run 
asynchronously (as a non-default option).

> > (we were thinking about python functions just scheduling multiple
> > actions and do stuff in parallel massively, but we quickly got into lot
> > of corner cases)
> > 
> > - each high-level function takes a LmiNamespace parameter, which
> > specifies the WBEM connection + the namespace on which it operates
> > -> i.e. applications/other scripts can run our functions on multiple
> > connections
> > -> if the LmiNamespace is not provided by caller, some 'global' one will
> > be used (so users just connect once and this connection is then used for
> > all high-level functions)
> 
> Having two extra parameters for each function sounds like a huge API bloat.
> I think that having some 'global' one, i.e. some kind of a state object
> that the underlying layer (lmishell?) would use, would be better.

One have to add the namespace parameter only one (in constructor) in the 
object-based approach.

> > - we should probably split these high-level function to several modules
> > by functionality, i.e. have lmi.networking and lmi.storage.vg,
> > lmi.storage.lv etc.
> > 
> > - it should be easy to build command-line versions for these high-level
> > functions
> > -> it is not clear if we should mimic existing cmdline tools (mdadm,
> > vgcreate, ip, ...) or make some cleanup (so creation of MD raid looks
> > the same like creation of a VG)

I would go for creating new set of commands and not to mimic existing cmdline 
tools. This new tools should follow the scripton API closely so user familiar 
with scriptons will feel comfortable when using the cmdline tools and vice 
versa.

> > - we should introduce some 'lmi' metacommand, which would wrap these
> > command line tools, like 'lmi vgcreate mygroup /dev/sda1 /dev/sdb1' and
> > 'lmi ip addr show'. It's quite similar to fedpkg or koji command line
> > utilities.
> > 
> > - 'lmi' metacommand could also have a shell:
> > $ lmi shell
> > 
> >> vgcreate mygroup /dev/sda1 /dev/sdb1
> >> ip addr show
> 
> I would go with the metacommand style (ala virsh).

I don't know, do we really want to have two "shells"? One lmishell for bare 
CIM access, and second one for running scriptions. Isn't it better to 
integrate both of them to one shell?

> > I tried to create a simple module for volume group management. I ran
> > into several issues with lmishell (see trac tickets), attached you can
> > find first proposal. It's quite crude and misses several important
> > aspects like proper logging and error handling.
> > 
> > Please look at it and let us know what you think. It is just a proposal,
> > we can change it in any way.
> > 
> > Once we agree on the concept, we must also define strict documentation
> > and logging standards so all functions and scripts are nicely documented
> > and all of them 

> > provide the same user experience.

Yeah, this is the most important part of doing scriptons at all. We already 
have the lowlevel ugly API that can do almost everything one can imagine 
(CIM). We should focus on how to make it usable for our users, to make it 
comfortable to use and make it consistent.

Radek Novacek



More information about the openlmi-devel mailing list