BIND 10 #213: Change hard-coded process startups to configuration-driven

BIND 10 Development do-not-reply at isc.org
Thu Oct 27 22:50:30 UTC 2011


#213: Change hard-coded process startups to configuration-driven
-------------------------------------+-------------------------------------
                   Reporter:  shane  |                 Owner:  vorner
                       Type:         |                Status:  reviewing
  enhancement                        |             Milestone:
                   Priority:  major  |  Sprint-20111108
                  Component:  Boss   |            Resolution:
  of BIND                            |             Sensitive:  0
                   Keywords:         |           Sub-Project:  Core
            Defect Severity:  N/A    |  Estimated Difficulty:  9
Feature Depending on Ticket:         |           Total Hours:
        Add Hours to Ticket:         |
                  Internal?:  0      |
-------------------------------------+-------------------------------------

Comment (by jinmei):

 Replying to (the rest of) [comment:19 vorner]:

 > > - It seems to make sense to allow derived class to override some of
 > >   the methods.  But I suspect the requirement to the overridden
 > >   methods should be more clarified [...]
 >
 > I added some documentation.

 Ack.  One small point in the revised doc:
 {{{
         You should also register any processes started within boss.
 }}}
 If this is something that all derived class (whether overridden or
 not) should meet, maybe we should move it to start().

 > > - A related point to the previous general issue, but not specific to
 > >   that: strange thing will happen if pid() is called before _procinfo
 > >   is set (e.g., at the "Init" state).  Also, what should happen if
 > >   this method is called without the underlying process?  Further, this
 > >   is actually not specific to PID, but also generally applicable to
 > >   _procinfo.
 >
 > The _procinfo should not be accessed if it's not running and it should
 in fact be more private than protected. I'm not sure if I access it from
 some kind of tests, or if it's leftover from some older version. Anyway,
 pid() now checks and returns None if it's not running (or derived
 component is bad).

 Maybe the accessibility assumption for _procinfo should be clearly
 documented.  As for pid(), I guess the (more) proper condition is
 `if self._procinfo is not None` here:
 {{{
         return self._procinfo.pid if self._procinfo else None
 }}}
 or revise the whole statement to:
 {{{
         return None if self._procinfo is None else self._procinfo.pid
 }}}
 (same comment applies to `kill()`).

 Also, for pid() to always work correctly, I suspect we should reset
 _procinfo to None once the component stops running.

 > > - On the specific point of the relationship between start_internal()
 > >   and _procinfo, I guess it's better to request derived method not
 > >   modify base attributes and instead return an ProcessInfo object as a
 > >   contract.  The start() method will then set _procinfo to the
 > >   returned value, and we can make sure _procinfo is always valid as
 > >   long as start() succeeds.
 >
 > I think there are none that modify it. This is actually what _start_func
 hook is for, it returns the procinfo and the rest is handled the usual
 way.
 >
 > Overriding start_internal is for bigger differences, where there might
 be no procinfo involved or no process (therefore PID) at all.
 >
 > I added some documentation there.

 Maybe my intent wasn't clearly delivered...let me rephrase it:
 Assume I wanted to completely override `_start_internal()` for some
 reason.  Then I should set `_procinfo` in the override version;
 otherwise kill() won't work correctly.  And, just like I commented
 about "You should also register..." part, if this is something all
 overridden the original implementation should do, I'd move it to
 start(), and (in this specific case) ask the implementor to return a
 `ProcessInfo` object from the overridden version of `_start_internal()`.
 Or, if you don't like that, at least we should document that
 `_procinfo` must be set in the overridden version of `_start_internal()`.

 > > - (A related point) Isn't it okay to not perform syntax check against
 > >   the given parameters? [...]
 >
 > It's not completely OK, but it's one of the TODO items (better error
 handling and checks). It currently implicitly relies on bindctl not
 allowing anything that's not allowed by spec file, but the checks should
 be definitelly added.

 Okay.

 > >   essentially specifies a specific derived Component class (if
 > >   explicitly specified).  So I'd rather simply call it something like
 > >   'component_class', specify the actual class Component class name
 > >   (e.g. 'SockCreator'), and use some reflection technique to
 > >   instantiate an object of the specified class.
 >
 > I'm not against some renaming (but the component_class is rather long
 and expects that someone has an idea what a class is). But I'd be against
 the reflection techniques, for one, they complicate tests, for another, I
 don't want the user to be able to type any class name there and expect
 things to work.

 It doesn't necessarily have to be reflection-like programming
 technique, but my point was that I'd like to separate the knowledge
 and process of how specific components should be created/killed from
 boss related modules, because it's ultimately something that only the
 author of that component can (and should) know.  So, for example, in
 my ideal world we'd write down how b10-auth should be spawned and
 killed somewhere and somehow, maybe as part of b10-config.db and/or in
 a form of plugin python module.  The boss process passes it to the
 component module mostly transparently, and eventually performs the
 required spawning steps, again, transparently.

 I'd also envision some external developers want to use the BIND 10
 framework to control a third party server process and want the boss
 process to invoke the third party server without modifying the BIND 10
 source code.  My overall point is that I'd like this framework to have
 this type of flexibility.  Whether to use the so-called "reflection"
 is implementation details.  But in any case, I don't think we need it
 today, especially not in this ticket, so I'm not insisting this should
 be solved within this task.

 As for the name, 'special' sounded too vague to me.  But naming is
 often a bikeshed matter (while sometimes it's very important), so as
 long as it's clearly documented we should probably focus on more
 important points.

 > > - _run_plan(): Like the configuration, I'd like to see doc string that
 > >   explains more details of 'plan'.
 >
 > I added a little bit, but that thing is mostly private to the
 configurator and tests.

 I know it's private.  My point is that we need some form of
 documentation that helps people who try to understand (and perhaps
 modify) the implementation.  It may not necessarily have to be doc string.

 > > - A related comment: since _old_config and _components are inter
 > >   related (and have one-to-one relationships if I understand it
 > >   correctly), I'd rather manage them in a combined way, e.g.
 > > {{{
 > >   _components = { 'msgq': (comonent_obj, componet_config), ... }
 > > }}}
 > >   That way we can be more sure, when reading the code, about the
 > >   consistency between them, and it will be easier to ensure the
 > >   consistency at least per component basis.

 > I implemented this.

 Change (18e970e1) looks okay, but using two different words
 'config(uration)' and 'spec' is confusing.  Please unify them.

 > But should we try some kind of rollback in case of failure-to-start or
 something?

 Ideally, but I suspect it's very difficult if not impossible because
 spawning/killing a process is not always a reversible operation.  If
 and when we clarify the relationship between the process status and
 component status (discussed in my previous comment message) we may be
 able to solve this in a cleaner way (for example, we may be able to
 ensure that Configurator.reconfigure() itself doesn't involve
 a non-reversible operation).  But for now, I suspect it's too
 difficult and should be remove from the scope of the ticket.

 > > - The exception message seems to be too broad:
 > > {{{
 > >                         raise NotImplementedError('Changing
 configuration of' +
 > >                                                   ' a running
 component is ' +
 > >                                                   'not yet supported.
 Remove' +
 > >                                                   ' and re-add ' +
 cname +
 > >                                                   'to get the same
 effect')
 > > }}}
 > >   because it only checks a subset of known configuration parameters
 > >   (e.g. even if 'address' is modified it doesn't complain)
 >
 > Not checking address was actually a bug (as the check was there before
 the address was added). Anyway, I'd like this one to go sometime soon and
 be able to handle the change if at all possible without bothering the
 user.

 Hardcoding the (un)expected items is quite error prone (it easily
 causes inconsistency), but considering it a short term workaround, I
 wouldn't bother further.  Also we'll need a space before 'to' here:
 {{{
                                                   'to get the same
 effect')
 }}}
 but, again, if it's short term it doesn't matter much anyway.

 > > - is it okay to allow Configurator.reconfigure() to even stop core
 > >   components?  It seems to contradict the idea that the system cannot
 > >   even start if such components fail to start.
 >
 > Yes, as described at the class's docstring, it's up to the caller to
 ensure this doesn't happen (and boss does that by making sure the three
 core components are always there).

 Okay, but do you mean this?
 {{{
     Note that this will allow you to stop (by invoking reconfigure) a core
     component. There should be some kind of layer protecting users from
 ever
     doing so (users must not stop the config manager, message queue and
 stuff
     like that or the system won't start again).
 }}}
 I fail to understand that this means that the caller shouldn't stop a
 core component.  It's probably better to describe that more
 explicitly.

 > > - what should happen if we do Configurator.shutdown() and try to
 > >   start it again?  Is it expected to be an okay behavior?  Unexpected
 > >   but not prohibited?  Or should be prohibited?
 >
 > I didn't think about that one. Boss doesn't use it so and I don't think
 there ever will be another user than a boss.
 >
 > But I guess it would work, so I wouldn't bother forbidding it explicitly
 or making sure it does unless it's really needed.

 I have no strong opinion about what it should be, but it's probably
 worth noting that it's not expected behavior but not explicitly
 prohibited (for now).

-- 
Ticket URL: <http://bind10.isc.org/ticket/213#comment:26>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development


More information about the bind10-tickets mailing list