[Openstack] cfg usage - option registration, global objects

Duncan McGreggor duncan at dreamhost.com
Thu May 31 20:44:32 UTC 2012


On Thu, May 31, 2012 at 4:21 PM, Mark McLoughlin <markmc at redhat.com> wrote:
> Hi Mark,
>
> On Thu, 2012-05-31 at 10:48 -0400, Mark Washenberger wrote:
>>
>> "Jay Pipes" <jaypipes at gmail.com> said:
>> > On 05/29/2012 04:04 AM, Mark McLoughlin wrote:
>> >> 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.
>> >
>> > Unfortunately, what this leads to is interdependencies between the
>> > openstack-common-rpc code and the openstack-common-cfg code. :( Now, if
>> > someone wants to use the openstack RPC code in their own project, they
>> > have to switch their way of configuring stuff to use global config
>> > objects. Tight coupling means less adherence to the "do one thing and do
>> > it well" mantra of *nix utilities and libraries and in general isn't
>> > good software design.
>>
>>
>> I personally would consider a rigid connection between the rpc library and
>> the configuration to be inappropriate in the context of openstack common.
>
> This is a fairly general design question for openstack-common.
>
> If the behaviour of any given API should be dependent on the
> configuration of the service (i.e. in nova.conf, glance-api.conf,
> keystone.conf), then how should we design the API to handle that?
>
> Three options:
>
>  1) The API knows nothing about cfg:
>
>     class Connection(object):
>
>         def __init__(self, broker_hostname, broker_port):
>             self.cnx = self.connect(broker_hostname, broker_port)
>
>         def cast(self, topic, msg):
>             self.cnx.cast(topic, msg)
>
>  2) The API is passed a ConfigOpts instance:
>
>     class Connection(object):
>
>         def __init__(self, conf):
>             self.cnx = self.connect(conf.broker_hostname,
>                                     conf.broker_port)
>
>         def cast(self, topic, msg):
>             self.cnx.cast(topic, msg)
>
>  3) The API uses the global config object
>
>     class Connection(object):
>
>         def __init__(self):
>             self.cnx = self.connect(CONF.broker_hostname,
>                                     CONF.broker_port)
>
>         def cast(self, topic, msg):
>             self.cnx.cast(topic, msg)
>
>
> I see (1) as having value if we want the API to be usable outside
> OpenStack. That might be worthwhile long term, but openstack-common's
> goal is to provide APIs shared between OpenStack projects.
>
> (2) and (3) have the huge benefit of configuration consistency - the
> same configuration keys, defaults, etc. shared across projects.
>
> (2) has value if there are cases where we want to use a non-global cfg
> object. Quantum might have this use case if it continues parsing plugin
> configuration separately from its main configuration. We'll see.
>
> (3) has value if all use cases are using a global object.

Also note that a configuration registry (per my previous email) can
satisfy both approaches outlined in 2) and 3).

d




More information about the Openstack mailing list