Re: [Openstack] cfg usage - option registration, global objects

2012-06-06 Thread Doug Hellmann
On Wed, Jun 6, 2012 at 10:58 AM, Mark McLoughlin mar...@redhat.com wrote:

 On Tue, 2012-06-05 at 17:25 -0400, Mark Washenberger wrote:
 
  Mark McLoughlin mar...@redhat.com said:
 
   On Tue, 2012-06-05 at 12:21 -0400, Mark Washenberger wrote:
http://wiki.openstack.org/CommonLibrary#Incubation
  
   Once an api is in incubation, if you make a change to it, you are
   expected to update all the other openstack projects (not just core
   projects?) to make them work with the new api. Am I understanding this
   requirement correctly?
  
   Yes, pretty much.

 I should clarify this - I don't think someone improving an API in
 openstack-common absolutely must update all projects that use it, but I
 think he/she often will update the major users to make sure the new API
 works.

 But the reality is that projects which use openstack-common need to be
 prepared that someday they might re-sync with latest openstack-common
 using update.py and find the API has changed.

   The alternative is that you don't make backwards
   incompatible API changes.
 
  ...
 
  
   What alternative strategy are you suggesting? That if glance, quantum,
   cinder and ceilometer want to re-use Nova's RPC code, they should
   copy-and-paste it and hack it to their needs?
 
  I don't think our only options here are immediate adoption and relative
  chaos.
 
  Here's what I would like to see:
 
  Quantum, cinder, and ceilometer get together, recognize a shared need
  for rpc, acknowledge the successes and failures of the nova.rpc library,
  and create a better implementation with eventual adoption by Nova kept
  in mind.
 
  Doesn't that sound better? This approach seems much nicer to me,
  because I believe that code reuse is likely to be detrimental unless
  the code we're talking about was created with reuse and generality
  in mind. Since I find that suggestion implausible regarding nova.rpc
  in particular, I think we will do better overall avoiding its wider
  adoption.
 
  Please, forgive me if I'm being drawn in falsely by the allure of better
  code. Code structure and quality *is* something I obsess about. But I
  appreciate the need to be practical in the short term as well, if I am
  not always the best at articulating it. The agreement from various
  quarters about the problems with the current nova.rpc gave me hope
  that we could craft a better rpc library without too much delay, even
  if I myself can only contribute in a small way to that effort.

 I think the summary is that you'd like (someone else?) to start from
 scratch on a new RPC API in openstack-common, whereas Russell has gone
 for the approach of taking Nova's RPC API and improving it iteratively.

 In the absence of someone appearing with that new idealised RPC API, I
 think it's reasonable for Russell to proceed with his approach.


Yes, please, keep going! We're too close now to stop now. I do have some
enhancements to propose, but I think I can make them in a backwards
compatible way once the existing code is in the common lib.

Ceilometer is currently importing bits we need either directly from nova or
openstack-common (by importing I mean literally using the import
statement in our code, not copying the required modules into the ceilometer
code base). I was under the impression that this is how we wanted (new)
projects to use openstack-common, but maybe I misunderstood? Should we be
planning to copy code out of openstack-common into the ceilometer
repository?

Doug
___
Mailing list: https://launchpad.net/~openstack
Post to : openstack@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp


Re: [Openstack] cfg usage - option registration, global objects

2012-06-06 Thread Mark McLoughlin
On Wed, 2012-06-06 at 12:05 -0400, Doug Hellmann wrote:
 Ceilometer is currently importing bits we need either directly from nova or
 openstack-common (by importing I mean literally using the import
 statement in our code, not copying the required modules into the ceilometer
 code base). I was under the impression that this is how we wanted (new)
 projects to use openstack-common, but maybe I misunderstood? Should we be
 planning to copy code out of openstack-common into the ceilometer
 repository? 

Yep, the rpc code will be in incubation for a while:

http://wiki.openstack.org/CommonLibrary

Add an openstack-common.conf and use update.py to sync it across.

Cheers,
Mark.


___
Mailing list: https://launchpad.net/~openstack
Post to : openstack@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp


Re: [Openstack] cfg usage - option registration, global objects

2012-06-06 Thread Mark Washenberger
 But the reality is that projects which use openstack-common need to be
 prepared that someday they might re-sync with latest openstack-common
 using update.py and find the API has changed.

That sounds good, especially during the early parts of incubation.

 In the absence of someone appearing with that new idealised RPC API, I
 think it's reasonable for Russell to proceed with his approach.

Looking more closely at Russell's improvements, and thinking about the
big changes I think we ought to make, it seems he's done a lot of the
good work already. I would like for us to kick the global and C-style
polymorphism habits in rpc, but I guess the best I can do is try to
add these changes after its in common.

Sorry if this has already been posted somewhere and I just can't find it,
but is there an openstack common weekly meeting where you guys talk about
your blueprints and determine what is going into common and in what form?
I think I can be less disruptive if I'm involved in these discussions much
earlier.

Mark McLoughlin mar...@redhat.com said:

 On Tue, 2012-06-05 at 17:25 -0400, Mark Washenberger wrote:

 Mark McLoughlin mar...@redhat.com said:

  On Tue, 2012-06-05 at 12:21 -0400, Mark Washenberger wrote:
   http://wiki.openstack.org/CommonLibrary#Incubation
 
  Once an api is in incubation, if you make a change to it, you are
  expected to update all the other openstack projects (not just core
  projects?) to make them work with the new api. Am I understanding this
  requirement correctly?
 
  Yes, pretty much.
 
 I should clarify this - I don't think someone improving an API in
 openstack-common absolutely must update all projects that use it, but I
 think he/she often will update the major users to make sure the new API
 works.
 
 But the reality is that projects which use openstack-common need to be
 prepared that someday they might re-sync with latest openstack-common
 using update.py and find the API has changed.
 
  The alternative is that you don't make backwards
  incompatible API changes.

 ...

 
  What alternative strategy are you suggesting? That if glance, quantum,
  cinder and ceilometer want to re-use Nova's RPC code, they should
  copy-and-paste it and hack it to their needs?

 I don't think our only options here are immediate adoption and relative
 chaos.

 Here's what I would like to see:

 Quantum, cinder, and ceilometer get together, recognize a shared need
 for rpc, acknowledge the successes and failures of the nova.rpc library,
 and create a better implementation with eventual adoption by Nova kept
 in mind.

 Doesn't that sound better? This approach seems much nicer to me,
 because I believe that code reuse is likely to be detrimental unless
 the code we're talking about was created with reuse and generality
 in mind. Since I find that suggestion implausible regarding nova.rpc
 in particular, I think we will do better overall avoiding its wider
 adoption.

 Please, forgive me if I'm being drawn in falsely by the allure of better
 code. Code structure and quality *is* something I obsess about. But I
 appreciate the need to be practical in the short term as well, if I am
 not always the best at articulating it. The agreement from various
 quarters about the problems with the current nova.rpc gave me hope
 that we could craft a better rpc library without too much delay, even
 if I myself can only contribute in a small way to that effort.
 
 I think the summary is that you'd like (someone else?) to start from
 scratch on a new RPC API in openstack-common, whereas Russell has gone
 for the approach of taking Nova's RPC API and improving it iteratively.
 
 In the absence of someone appearing with that new idealised RPC API, I
 think it's reasonable for Russell to proceed with his approach.
 
 Cheers,
 Mark.
 
 
 ___
 Mailing list: https://launchpad.net/~openstack
 Post to : openstack@lists.launchpad.net
 Unsubscribe : https://launchpad.net/~openstack
 More help   : https://help.launchpad.net/ListHelp
 




___
Mailing list: https://launchpad.net/~openstack
Post to : openstack@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp


Re: [Openstack] cfg usage - option registration, global objects

2012-06-06 Thread Mark McLoughlin
On Wed, 2012-06-06 at 15:41 -0400, Mark Washenberger wrote:

 Sorry if this has already been posted somewhere and I just can't find it,
 but is there an openstack common weekly meeting where you guys talk about
 your blueprints and determine what is going into common and in what form?
 I think I can be less disruptive if I'm involved in these discussions much
 earlier.

We haven't been doing meetings, but there was a long thread on this a
while back:

  https://lists.launchpad.net/openstack/msg09456.html

Cheers,
Mark.


___
Mailing list: https://launchpad.net/~openstack
Post to : openstack@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp


Re: [Openstack] cfg usage - option registration, global objects

2012-06-05 Thread Mark McLoughlin
On Fri, 2012-06-01 at 10:37 -0400, Mark Washenberger wrote:
 Hi Mark,
 
 Please forgive the top-posting! I always get way too wordy with
 inline replies.
 
 Regarding configuration, I think there is another option I'd like us
 to adopt. We should implement the code as in your option #1, but then
 implement convenience factories that give the appearance of option #3
 or #2, or both, you pick. From your examples it might look something
 like this:
 
 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)
 
 def connection_from_global_conf():
 return Connection(CONF.broker_hostname, CONF.broker_port)
 
 I think its pretty necessary that we don't do option #3 directly.
 There are some important use cases to consider, like migrating from
 one rpc implementation to another where you might want an adapter
 that can relay messages from one to the other. Also, cells with
 kombu at least requires that one process be able to talk to multiple
 brokers.

Yeah, I think that all makes sense.

Depending on the context, we might want to require only one of #1, #2 or
#3 to be supported in order for the API to be added to openstack-common
initially. I think there'll be good reasons in different cases why only
one of the options is required by initial users of the API.

 Regarding incubation, I suppose I am confused. At what point during
 incubation do other projects start to use the shared library? I would
 imagine the answer to be after incubation but it sounds like there
 are several projects very eager to adopt rpc as soon as it lands in
 openstack common, even before incubation is complete.
 
 If incubation happens before the calcifying effects of shared use
 set in, then it sounds like a great place to address the other
 rpc-specific concerns we've talked about. Otherwise I guess we're
 stuck where I thought we were, where the bar needs to be set pretty
 high to initially land in os-common.

http://wiki.openstack.org/CommonLibrary#Incubation

In openstack-common, Incubation - Core is we're ready to commit to
backward compatibility. None of the APIs have reached that point yet.

While an API is incubating, other projects can still use it and the API
can make backwards incompatible changes. For example, I made a backwards
incompatible change to the cfg.ConfigOpts() constructor recently and
updated all projects to use the new API.

That's exactly the case here - we want openstack.common.rpc to initially
be a reasonable API that can be used by multiple OpenStack projects (say
nova, glance and quantum) but that doesn't mean we need to commit to
maintaining backwards compatibility for the API we initially add.

Cheers,
Mark.


___
Mailing list: https://launchpad.net/~openstack
Post to : openstack@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp


Re: [Openstack] cfg usage - option registration, global objects

2012-06-05 Thread Duncan McGreggor
+1 :-)

d

On Fri, Jun 1, 2012 at 10:37 AM, Mark Washenberger
mark.washenber...@rackspace.com wrote:
 Hi Mark,

 Please forgive the top-posting! I always get way too wordy with
 inline replies.

 Regarding configuration, I think there is another option I'd like us
 to adopt. We should implement the code as in your option #1, but then
 implement convenience factories that give the appearance of option #3
 or #2, or both, you pick. From your examples it might look something
 like this:

    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)

    def connection_from_global_conf():
        return Connection(CONF.broker_hostname, CONF.broker_port)

 I think its pretty necessary that we don't do option #3 directly.
 There are some important use cases to consider, like migrating from
 one rpc implementation to another where you might want an adapter
 that can relay messages from one to the other. Also, cells with
 kombu at least requires that one process be able to talk to multiple
 brokers.

 Regarding incubation, I suppose I am confused. At what point during
 incubation do other projects start to use the shared library? I would
 imagine the answer to be after incubation but it sounds like there
 are several projects very eager to adopt rpc as soon as it lands in
 openstack common, even before incubation is complete.

 If incubation happens before the calcifying effects of shared use
 set in, then it sounds like a great place to address the other
 rpc-specific concerns we've talked about. Otherwise I guess we're
 stuck where I thought we were, where the bar needs to be set pretty
 high to initially land in os-common.

 Mark McLoughlin mar...@redhat.com said:

 Hi Mark,

 On Thu, 2012-05-31 at 10:48 -0400, Mark Washenberger wrote:

 Jay Pipes jaypi...@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.

 I can see us getting to a point where we support both (2) and (3). I'm
 dubious of the value of (1) in the medium term, but maybe we might find
 a compelling use case for it.

 I'm also very happy to contribute modifications that would eliminate that
 connection.

 There are a few other reasons 

Re: [Openstack] cfg usage - option registration, global objects

2012-06-05 Thread Mark McLoughlin
On Tue, 2012-06-05 at 12:48 -0400, Duncan McGreggor wrote:
 +1 :-)

In all seriousness - Mark made two separate points. Which one are you
top-posting a +1 to?

 On Fri, Jun 1, 2012 at 10:37 AM, Mark Washenberger
 mark.washenber...@rackspace.com wrote:
  Hi Mark,
 
  Please forgive the top-posting! I always get way too wordy with
  inline replies.

point 1

  Regarding configuration, I think there is another option I'd like us
  to adopt. We should implement the code as in your option #1, but then
  implement convenience factories that give the appearance of option #3
  or #2, or both, you pick. From your examples it might look something
  like this:
 
 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)
 
 def connection_from_global_conf():
 return Connection(CONF.broker_hostname, CONF.broker_port)
 
  I think its pretty necessary that we don't do option #3 directly.
  There are some important use cases to consider, like migrating from
  one rpc implementation to another where you might want an adapter
  that can relay messages from one to the other. Also, cells with
  kombu at least requires that one process be able to talk to multiple
  brokers.

/point 1

point 2

  Regarding incubation, I suppose I am confused. At what point during
  incubation do other projects start to use the shared library? I would
  imagine the answer to be after incubation but it sounds like there
  are several projects very eager to adopt rpc as soon as it lands in
  openstack common, even before incubation is complete.
 
  If incubation happens before the calcifying effects of shared use
  set in, then it sounds like a great place to address the other
  rpc-specific concerns we've talked about. Otherwise I guess we're
  stuck where I thought we were, where the bar needs to be set pretty
  high to initially land in os-common.

/point 2

Cheers,
Mark.


___
Mailing list: https://launchpad.net/~openstack
Post to : openstack@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp


Re: [Openstack] cfg usage - option registration, global objects

2012-06-05 Thread Russell Bryant
On 06/05/2012 05:35 PM, Russell Bryant wrote:
 On 06/05/2012 05:25 PM, Mark Washenberger wrote:


 Mark McLoughlin mar...@redhat.com said:

 On Tue, 2012-06-05 at 12:21 -0400, Mark Washenberger wrote:
 http://wiki.openstack.org/CommonLibrary#Incubation

 Once an api is in incubation, if you make a change to it, you are
 expected to update all the other openstack projects (not just core
 projects?) to make them work with the new api. Am I understanding this
 requirement correctly?

 Yes, pretty much. The alternative is that you don't make backwards
 incompatible API changes.

 ...


 What alternative strategy are you suggesting? That if glance, quantum,
 cinder and ceilometer want to re-use Nova's RPC code, they should
 copy-and-paste it and hack it to their needs?

 I don't think our only options here are immediate adoption and relative
 chaos.

 Here's what I would like to see:

 Quantum, cinder, and ceilometer get together, recognize a shared need
 for rpc, acknowledge the successes and failures of the nova.rpc library,
 and create a better implementation with eventual adoption by Nova kept
 in mind.

 Doesn't that sound better? This approach seems much nicer to me,
 because I believe that code reuse is likely to be detrimental unless
 the code we're talking about was created with reuse and generality
 in mind. Since I find that suggestion implausible regarding nova.rpc
 in particular, I think we will do better overall avoiding its wider
 adoption.

 Please, forgive me if I'm being drawn in falsely by the allure of better
 code. Code structure and quality *is* something I obsess about. But I
 appreciate the need to be practical in the short term as well, if I am
 not always the best at articulating it. The agreement from various
 quarters about the problems with the current nova.rpc gave me hope
 that we could craft a better rpc library without too much delay, even
 if I myself can only contribute in a small way to that effort.
 
 That all sounds nice in theory, but like you alluded to here, who
 specifically is going to sign up to do that?  I can finish the move of
 the current code (I have it ready to propose, actually), but I have
 other things I should work on after that.
 
 How about the stakeholders interested in using this code in other
 projects?  Do you want the current code in now (with the likelihood of
 having to adapt to some API changes later), or would you like to get
 together and work on something new?  If so, I'll just toss the proposal
 of the current code for common and let someone else drive the new thing
 in instead.
 

By the way, the move of the current code is ready if we agree to
proceed with it:

https://review.openstack.org/#/c/8206/

-- 
Russell Bryant

___
Mailing list: https://launchpad.net/~openstack
Post to : openstack@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp


Re: [Openstack] cfg usage - option registration, global objects

2012-06-01 Thread Gary Kotton

On 06/01/2012 12:47 AM, Russell Bryant wrote:

On 05/31/2012 04:21 PM, Mark McLoughlin wrote:

I expect to do a pretty detailed review of the patch to add rpc to
openstack-common and make some API design recommendations. But I think
we'll have to balance some of those design ideas between stuff we
really should fix before it goes into openstack-common vs stuff that
would need to be fixed before the API comes out of incubation.

  I've been pushing the code with a goal that the submission to
openstack-common is *only* a matter of changing the imports.  Up to this
point, it has mostly been a matter of removing dependencies on other
parts of nova.  We are actually at that point now ... unless there are
other changes that are going to block it.

I'd rather just work on improvements people would like to see while the
code is in incubation in openstack-common.  People are already copying
it (in a feature branch for Quantum, Cinder, the Heat project, at
least), so moving it as is will leave us in a better spot than we are now.
I agree with Russell. On the Quantum side we are waiting for the code so 
that we can move ahead with a number of blueprints. I understand that 
there is also a solution for versioning.

Thanks
Gary

___
Mailing list: https://launchpad.net/~openstack
Post to : openstack@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp


Re: [Openstack] cfg usage - option registration, global objects

2012-05-31 Thread Mark Washenberger


Jay Pipes jaypi...@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.
I'm also very happy to contribute modifications that would eliminate that
connection.

There are a few other reasons I'm concerned about nova's rpc implementation
becoming the de facto standard. It has grown up organically and as such has
some significant issues we should probably address before we create a
precedent that other projects must adopt it to be good community members.

From a brief scan, it seems to me that a restructured implementation of rpc
that lands in common should

 * not be tied up with eventlet on the consumer side
 * let the consumer code decide when to ack a message
   (although maybe the concept of acking doesn't exist for all implementations?)
 * not depend on a global singleton _RPC_IMPL
 * leave out/refactor some unused or non-general aspects, such as multicall,
   fanout_cast_to_server, notify, and fanout_cast (not so sure about that last 
one)

I'm happy to work on some of these but I probably can't do the whole thing.



___
Mailing list: https://launchpad.net/~openstack
Post to : openstack@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp


Re: [Openstack] cfg usage - option registration, global objects

2012-05-31 Thread Doug Hellmann
On Thu, May 31, 2012 at 10:48 AM, Mark Washenberger 
mark.washenber...@rackspace.com wrote:



 Jay Pipes jaypi...@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.
 I'm also very happy to contribute modifications that would eliminate that
 connection.

 There are a few other reasons I'm concerned about nova's rpc implementation
 becoming the de facto standard. It has grown up organically and as such has
 some significant issues we should probably address before we create a
 precedent that other projects must adopt it to be good community members.

 From a brief scan, it seems to me that a restructured implementation of rpc
 that lands in common should

  * not be tied up with eventlet on the consumer side
  * let the consumer code decide when to ack a message
   (although maybe the concept of acking doesn't exist for all
 implementations?)
  * not depend on a global singleton _RPC_IMPL
  * leave out/refactor some unused or non-general aspects, such as
 multicall,
   fanout_cast_to_server, notify, and fanout_cast (not so sure about that
 last one)


It would also be useful if it had a way to subscribe to notification
messages. From what I can tell, notifications don't work with any of the
consumers in the existing drivers because those consumers all want to
dispatch to a method invocation, but notifications aren't structured
appropriately for that.

I would like to abstract the messaging layer out of the existing nova RPC
library and then build a compatible RPC layer on top of it. Notifications
and other simple messages (such as meter data for ceilometer) would use the
lower layer, and communication that truly works like RPC could use the
higher level API. We should be able to build an agnostic RPC layer that
uses the messaging driver, instead of having the two concepts bound up
together.



 I'm happy to work on some of these but I probably can't do the whole thing.



 ___
 Mailing list: https://launchpad.net/~openstack
 Post to : openstack@lists.launchpad.net
 Unsubscribe : https://launchpad.net/~openstack
 More help   : https://help.launchpad.net/ListHelp

___
Mailing list: https://launchpad.net/~openstack
Post to : openstack@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp


Re: [Openstack] cfg usage - option registration, global objects

2012-05-31 Thread Johannes Erdfelt
On Thu, May 31, 2012, Mark Washenberger mark.washenber...@rackspace.com wrote:
  * not be tied up with eventlet on the consumer side

Yes!

  * let the consumer code decide when to ack a message
(although maybe the concept of acking doesn't exist for all 
 implementations?)

My XenAPI idempotency branch delays ACKs until after it's done processing
the message to ensure we get the message again after restart.

https://review.openstack.org/#/c/7323

I can't say that I'm happy with the changes I've made to safely support
delayed ACKs.

As far as implementations go, the Qpid docs say messages should be
acknowledged, but I don't see anywhere in the code where that happens.
I haven't dug too far into it to figure out this discrepancy.

While the 0MQ code hasn't been merged yet, 0MQ appears to have no concept
of acknowledging messages.

Between the messy code in supporting delayed ACKs and the fact that some
RPC implementations don't appear to support ACKs at all, it may mean
reliability will need to be implemented elsewhere.

The proposed orchestration work could possibly work as an alternative.

JE


___
Mailing list: https://launchpad.net/~openstack
Post to : openstack@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp


Re: [Openstack] cfg usage - option registration, global objects

2012-05-31 Thread Duncan McGreggor
On Thu, May 31, 2012 at 11:26 AM, Doug Hellmann
doug.hellm...@dreamhost.com wrote:


 On Thu, May 31, 2012 at 10:48 AM, Mark Washenberger
 mark.washenber...@rackspace.com wrote:



 Jay Pipes jaypi...@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.
 I'm also very happy to contribute modifications that would eliminate that
 connection.

 There are a few other reasons I'm concerned about nova's rpc
 implementation
 becoming the de facto standard. It has grown up organically and as such
 has
 some significant issues we should probably address before we create a
 precedent that other projects must adopt it to be good community members.

 From a brief scan, it seems to me that a restructured implementation of
 rpc
 that lands in common should

  * not be tied up with eventlet on the consumer side
  * let the consumer code decide when to ack a message
   (although maybe the concept of acking doesn't exist for all
 implementations?)
  * not depend on a global singleton _RPC_IMPL
  * leave out/refactor some unused or non-general aspects, such as
 multicall,
   fanout_cast_to_server, notify, and fanout_cast (not so sure about that
 last one)


 It would also be useful if it had a way to subscribe to notification
 messages. From what I can tell, notifications don't work with any of the
 consumers in the existing drivers because those consumers all want to
 dispatch to a method invocation, but notifications aren't structured
 appropriately for that.

 I would like to abstract the messaging layer out of the existing nova RPC
 library and then build a compatible RPC layer on top of it. Notifications
 and other simple messages (such as meter data for ceilometer) would use the
 lower layer, and communication that truly works like RPC could use the
 higher level API. We should be able to build an agnostic RPC layer that uses
 the messaging driver, instead of having the two concepts bound up together.

A very hearty +1.

d

___
Mailing list: https://launchpad.net/~openstack
Post to : openstack@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp


Re: [Openstack] cfg usage - option registration, global objects

2012-05-31 Thread Mark McLoughlin
Hi Mark,

On Thu, 2012-05-31 at 10:48 -0400, Mark Washenberger wrote:
 
 Jay Pipes jaypi...@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.

I can see us getting to a point where we support both (2) and (3). I'm
dubious of the value of (1) in the medium term, but maybe we might find
a compelling use case for it.

 I'm also very happy to contribute modifications that would eliminate that
 connection.
 
 There are a few other reasons I'm concerned about nova's rpc implementation
 becoming the de facto standard. It has grown up organically and as such has
 some significant issues we should probably address before we create a
 precedent that other projects must adopt it to be good community members.

other projects must adopt it to be good community members - that's an
interesting take, not the way I'd put it.

I think I'd say that if a project wants to do RPC, it makes more sense
to improve the RPC API in openstack-common to meet its needs rather than
start a from-scratch implementation or, worse, copy and paste what's
there and customize it.

 From a brief scan, it seems to me that a restructured implementation of rpc
 that lands in common should
 
  * not be tied up with eventlet on the consumer side

Sounds like a good and achievable goal. Is there or will there soon be
an OpenStack project that needs has this requirement in order to be able
to use this code?

  * let the consumer code decide when to ack a message
(although maybe the concept of acking doesn't exist for all 
 implementations?)

What's the use case?

  * not depend on a global singleton _RPC_IMPL

I agree.

  * leave out/refactor some unused or non-general aspects, such as multicall,
fanout_cast_to_server, notify, and fanout_cast (not so sure about that 
 last one)

i.e. leave out stuff that is specific to Nova? How about if e.g. Cinder
was using it?


Don't forget that openstack-common has this notion of incubating APIs.
Everything is in incubation at the moment. I'd say cfg is the closest to
coming out of incubation.

I expect to do a pretty detailed review of the patch to add rpc to
openstack-common and make some API design recommendations. But I think
we'll have to balance some of those design ideas between stuff we
really should fix before it goes into openstack-common vs stuff that
would need to be fixed 

Re: [Openstack] cfg usage - option registration, global objects

2012-05-31 Thread Mark McLoughlin
On Thu, 2012-05-31 at 08:58 -0700, Johannes Erdfelt wrote:
   * let the consumer code decide when to ack a message
 (although maybe the concept of acking doesn't exist for all
 implementations?)
 
 My XenAPI idempotency branch delays ACKs until after it's done
 processing the message to ensure we get the message again after
 restart.
 
 https://review.openstack.org/#/c/7323
 
 I can't say that I'm happy with the changes I've made to safely
 support delayed ACKs. 

Starting an instance is a long running operation. We confirm its
completion by updating the instance state in the DB. We could switch to
casting instance state change messages instead.

Point is, I'd see an ack as message received, I've acted on it and
handle the completion notification of long running messages separately.

Or put it another way, an ack for a long running operation is similar to
202 Accepted in a REST API.

Cheers,
Mark.


___
Mailing list: https://launchpad.net/~openstack
Post to : openstack@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp


Re: [Openstack] cfg usage - option registration, global objects

2012-05-31 Thread Duncan McGreggor
On Thu, May 31, 2012 at 4:21 PM, Mark McLoughlin mar...@redhat.com wrote:
 Hi Mark,

 On Thu, 2012-05-31 at 10:48 -0400, Mark Washenberger wrote:

 Jay Pipes jaypi...@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

___
Mailing list: https://launchpad.net/~openstack
Post to : openstack@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp


Re: [Openstack] cfg usage - option registration, global objects

2012-05-31 Thread Johannes Erdfelt
On Thu, May 31, 2012, Mark McLoughlin mar...@redhat.com wrote:
 On Thu, 2012-05-31 at 08:58 -0700, Johannes Erdfelt wrote:
  My XenAPI idempotency branch delays ACKs until after it's done
  processing the message to ensure we get the message again after
  restart.
  
  https://review.openstack.org/#/c/7323
  
  I can't say that I'm happy with the changes I've made to safely
  support delayed ACKs. 
 
 Starting an instance is a long running operation. We confirm its
 completion by updating the instance state in the DB. We could switch to
 casting instance state change messages instead.
 
 Point is, I'd see an ack as message received, I've acted on it and
 handle the completion notification of long running messages separately.
 
 Or put it another way, an ack for a long running operation is similar to
 202 Accepted in a REST API.

My only concern with this is that it pushes durability of the message
down a layer (assuming no orchestration).

It's probably unavoidable to maintain flexibility in the RPC layer, but
it does make things more complicated.

JE


___
Mailing list: https://launchpad.net/~openstack
Post to : openstack@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp


Re: [Openstack] cfg usage - option registration, global objects

2012-05-31 Thread Russell Bryant
On 05/31/2012 04:21 PM, Mark McLoughlin wrote:
 I expect to do a pretty detailed review of the patch to add rpc to
 openstack-common and make some API design recommendations. But I think
 we'll have to balance some of those design ideas between stuff we
 really should fix before it goes into openstack-common vs stuff that
 would need to be fixed before the API comes out of incubation.

 I've been pushing the code with a goal that the submission to
openstack-common is *only* a matter of changing the imports.  Up to this
point, it has mostly been a matter of removing dependencies on other
parts of nova.  We are actually at that point now ... unless there are
other changes that are going to block it.

I'd rather just work on improvements people would like to see while the
code is in incubation in openstack-common.  People are already copying
it (in a feature branch for Quantum, Cinder, the Heat project, at
least), so moving it as is will leave us in a better spot than we are now.

-- 
Russell Bryant

___
Mailing list: https://launchpad.net/~openstack
Post to : openstack@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp


Re: [Openstack] cfg usage - option registration, global objects

2012-05-30 Thread Jay Pipes

On 05/29/2012 04:04 AM, Mark McLoughlin 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.


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'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


Yes, I've noticed. :) I'm not a fan at all, but that said, it is more 
important to have consistency among the core projects IMHO, than to be 
ideologically pure on this point.


Hopefully others who are being ideologically stubborn about things like 
the multiprocessing library is broken can see to also being less 
stubborn so certain patches can move forward in code review...


Best,
-jay

___
Mailing list: https://launchpad.net/~openstack
Post to : openstack@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp


Re: [Openstack] cfg usage - option registration, global objects

2012-05-29 Thread Mark McLoughlin
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.

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 +, 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@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp


Re: [Openstack] cfg usage - option registration, global objects

2012-05-29 Thread Duncan McGreggor
On Tue, May 29, 2012 at 4:04 AM, Mark McLoughlin mar...@redhat.com 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 +, 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@lists.launchpad.net
 Unsubscribe : https://launchpad.net/~openstack
 More help   : https://help.launchpad.net/ListHelp

___
Mailing list: https://launchpad.net/~openstack
Post to : 

Re: [Openstack] cfg usage - option registration, global objects

2012-03-12 Thread Adam Young




Also, these global objects force us to do a bunch of hacks in unit
tests. We need to do tricks to ensure the object is initialized as
we want. We also need to save and restore its state between runs.


I don't agree with the statement that they force a bunch of hacks, 
clearing
state is a perfectly normal thing to do, it is done for any servers 
that get
started, any mocks that are made, and every test database. Making sure 
that
modifications to a configuration object are cleaned up is no 
different: there
is no save and restore just always start from a blank slate and set 
things

as required, same as in the non-global model.

But ensuring that we are back at tabular rasa is difficult with global 
objects and running tests in a single process space.  Many of the test 
cases are dependant on second order effects of function calls to 
configure internal objects, instead of being true unit tests that only 
call on a single object.


 This kind of refactoring is  the norm in large projects,  and leads to 
better tested code paths, reusuable objects,  and objects that are 
easier to understand and track.


One way that these types of things have been described is via the SOLID 
acronym.  THis is a collection of best practices:


http://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29

The Global config violates quite a few of these principals.  By reading 
from a configuration object,  you implicitly violate Single 
responsibility.  Now it has at least two,  one of which is figuring out 
how to construct and initialize itself.  It also doesn't really follow 
the Open Closed principal:  Once you get state from a Config object,  
you can no longer easily extend it,  unless that extended object also 
gets its state from the same config.  The big one is D:  Dependency.  By 
using a global config,  you make dependencies on implementations,  not 
abstractions.  Dependency injection is pretty much impossible with a 
global config.



Keystone really stands to benefit from reusability.  An example:  right 
now,  we can only have one SQL Datasource, but it is likely that some 
users would have one data source for Identity and a different one for 
Tokens.  That same set up has been describved for LDAP:  Using a 
centralized LDAP server for Authentication,  but a local one for 
Authorization.  To do that,  we have to split the LDAP config (and allow 
multiple) from the Identity config.







___
Mailing list: https://launchpad.net/~openstack
Post to : openstack@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp


Re: [Openstack] cfg usage - option registration, global objects

2012-03-09 Thread Mark Washenberger
Really not trying to derail, but

Mark McLoughlin mar...@redhat.com said:
 
 [..]
  Also, these global objects force us to do a bunch of hacks in unit
  tests. We need to do tricks to ensure the object is initialized as
  we want. We also need to save and restore its state between runs.
 

 I don't agree with the statement that they force a bunch of hacks,
 clearing state is a perfectly normal thing to do, it is done for any
 servers that get started, any mocks that are made, and every test
 database. Making sure that modifications to a configuration object are
 cleaned up is no different: there is no save and restore just always
 start from a blank slate and set things as required, same as in the
 non-global model.
 
 Creating mocks, DB connection objects or re-starting servers on each
 test run is different from trying to restore a global object to its
 state before a test run.
 
 The CONF object is initialized the first time the config module is
 imported. Each test run you need to attempt to reset the object back to
 its original pristine state. Compared to just creating a config object
 for each run, I do think that's a hack.
 

While I agree with what Mark is saying above, I really must
point out that any significant shared state among unit tests is
either a hack, or a smell, or most charitably, the wrong kind of
test to run with unit tests.

Any teardown that isn't just handled by the garbage collector is
a good clue that we're doing something suboptimally.


___
Mailing list: https://launchpad.net/~openstack
Post to : openstack@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp