← Back to team overview

openstack team mailing list archive

Re: cfg usage - option registration, global objects

 

On Tue, May 29, 2012 at 4:04 AM, Mark McLoughlin <markmc@xxxxxxxxxx> wrote:
> Hey,
>
> I had the chance to discuss the "global conf" issue with a good number
> of folks at the design summit and the conclusion I came away with was
> that opinions range from "meh, it's fairly inelegant but I don't care
> much either way" to "I actually like the simplicity" to "we use global
> conf, it works and we're not changing".
>
> Indeed, at the "common configuration patterns", there was very little in
> the way of opinion expressed at all:
>
>  http://etherpad.openstack.org/FolsomCommonConfigPatterns
>
> Given that my goal here is to establish a common pattern used by all
> projects, that both Nova and Keystone uses global conf and there isn't a
> huge amount of interest in moving away from it, I'm proposing adding
> support for it to openstack-common:
>
>  https://blueprints.launchpad.net/openstack-common/+spec/cfg-global-object
>
> Adopting this pattern across all projects will actually help
> openstack-common more generally. For example, Russell is moving the RPC
> code into openstack-common and it has a bunch of configuration options.
> If it can assume a global configuration object, things become much
> easier.

Though not a fan of global objects, I've used (and still do use) them
to "simplify" things. 99% of my usage of them in other projects are
for configuration, as one might expect. I've avoided this in the past
through passing parameters, but that often ends up quite messy and
rather cumbersome to trace when debugging. More often than not, even
when passed, configuration ends up getting used in contexts that are
almost global anyway.

If I do use a global object, I am deeply loathe to do it without the following:
 * ample documentation - how to use it, when not to use it, what one
needs to do first, etc.
 * an API for it - no direct use of an object itself

I have used zope.components to address the last point (the first one
being addressed by good discipline ;-) ). It's simple to use:

from zope.component import getGlobalSiteManager, getUtility
from zope.interface import Interface

class IConfig(Interface):
  """
  A marker interface for configuration instances.
  """

gsm = getGlobalSiteManager()
gsm.registerUtility(some_config_object, IConfig)

That's done once, often in the __init__.py of a subpackage. All child
modules and/or subpackages should need that configuration to be
declared. Any code that doesn't need such configuration should be in a
sibling (or higher) subpackage.

Any time you need the config object:

config = getUtility(IConfig)

Note that you can register any object using this approach (including
imported modules). The use of a marker interface may seem like
overkill, but it provides a very natural place for documentation.

Also, I usually wrap these calls in convenience functions in my
projects, making use as simple, self-documenting, and maintainable as
possible.

More benefits to this approach (and why I chose to use it):

I've got several projects (non-OpenStack) that have one or more other
projects as their base -- the base project defines a configuration
setup that is used in part or completely by the projects which depend
upon it. zope.components let's me use a global registry to look up a
config by interface, and this means that as long as a child project
registers its config before the parent/base project code does, the
base project code will be referencing the child projects configs. This
does require strong import discipline, and careful subpackage
organization, but I've found it a wonderful compromise for the global
configuration problem.

Note that the Pyramid project also uses the zope.components
capabilities for configuration registry, so you might want to check
out their code for potential use-cases.

Hope this is helpful,

d


>
> I've posted patches to openstack-common, Nova, Glance and Keystone:
>
>  https://review.openstack.org/#/q/status:open+branch:master+topic:bp/cfg-global-object,n,z
>
> Cheers,
> Mark.
>
> On Tue, 2012-03-06 at 10:10 +0000, Mark McLoughlin wrote:
>> Hey,
>>
>> The original cfg design[1] assumed certain usage patterns that I hoped
>> would be adopted by all projects using it. In gerrit, we're debating a
>> set of patch to make keystone use these patterns:
>>
>>   https://review.openstack.org/4547
>>
>> I thought it was best to move some of that discussion here since I'm
>> hoping we can get some rough consensus across projects. I really think
>> it will be beneficial if we can share common idioms and patterns across
>> projects, rather than just using the same library in different ways.
> [snip]
>
> Thread archived here:
>
>  https://lists.launchpad.net/openstack/msg08329.html
>
>
> _______________________________________________
> Mailing list: https://launchpad.net/~openstack
> Post to     : openstack@xxxxxxxxxxxxxxxxxxx
> Unsubscribe : https://launchpad.net/~openstack
> More help   : https://help.launchpad.net/ListHelp


References