Hi Simon,

I'm finally done with the review. That was quite long (spread over two
weeks), and obviously less than what it might have taken you to do this
work. Next time if you can send smaller chunks it might help a lot !

Due to the difficulty to assign enough continuous time on it, I used
"git notes" to add notes to the commits, which allowed me to go back
and forth in the review. So I have not commented inline the code but
I have so few comments about the code by itself that it should not be
an issue at all, I hope you don't mind. Otherwise ask me for details
and I'll happily go into depth.

I found one concern at the end about the external check that's probably
worth a separate discussion thread. I'm suspecting that we should probably
get the 20 first patches merged ASAP and discuss the last two after that.

I'm appending the whole review here. This is a git log --reverse which
shows my comments below the Notes: tags.

Thanks very much for this work, I hope we can sort out all remaining
points to get it merged into 1.5-dev20.

Best regards,
Willy

---

commit 08eff21897f3f5d62f1360f309c5a71da6146afa
Author: Simon Horman <ho...@verge.net.au>
Date:   Sat Feb 23 08:34:13 2013 +0900

    DOC: Clarify documentation of option lb-agent-chk
    
    Avoid referring to check-port as this is not a configuration parameter.
    
    Signed-off-by: Simon Horman <ho...@verge.net.au>

Notes:
    OK

commit bff65d578c2e4212dfcbfa14ba549581ca42bc1d
Author: Simon Horman <ho...@verge.net.au>
Date:   Sun Feb 24 07:45:56 2013 +0900

    CLEANUP: Make parameters of srv_downtime and srv_getinter const
    
    The parameters of srv_downtime and srv_getinter are not modified
    and thus may be const.
    
    Signed-off-by: Simon Horman <ho...@verge.net.au>

Notes:
    OK

commit 9386a28b61cb7fb011ef2e710616b972f7bfe4e3
Author: Simon Horman <ho...@verge.net.au>
Date:   Sat Feb 23 10:16:43 2013 +0900

    MEDIUM: Split up struct server's check element
    
    This is in preparation for associating a agent check
    with a server which runs as well as the server's existing check.
    
    The split has been made by:
    * Moving elements of struct server's check element that will
      be shared by both checks into a new check_common element
      of struct server.
    * Moving the remaining elements to a new struct check and
      making struct server's check element a struct check.
    * Adding a server element to struct check, a back-pointer
      to the server element it is a member of.
      - At this time the server could be obtained using
        container_of, however, this will not be so easy
        once a second struct check element is added to struct server
        to accommodate an agent health check.
    
    Signed-off-by: Simon Horman <ho...@verge.net.au>
    
    ---
    
    v6
    * Correct use of srv->check_common.xprt ssl_sock_prepare_srv_ctx().
      Previously srv->check.xprt was used which causes a build failure
      when compiled with make USE_OPENSSL=1 ...
      Thanks to Scott McKeown for discovering this.
    
    v2 - v5
    * No change

Notes:
    OK.

commit ed27bc9796c5d0c06e1dc3dad4774510b3f1277a
Author: Simon Horman <ho...@verge.net.au>
Date:   Sun Feb 24 09:09:03 2013 +0900

    MEDIUM: Move {,fast,down}inter to struct check
    
    Move {,fast,down}inter elements from struct server to struct check.
    This allows those elements of a check to be independent of the check's 
server.
    
    This is in preparation for associating a agent check
    with a server which runs as well as the server's existing check.
    
    Signed-off-by: Simon Horman <ho...@verge.net.au>

Notes:
    OK though could probably be merged with previous one

commit 368f15d3ad805edbbc9070e708ce5b99624a8607
Author: Simon Horman <ho...@verge.net.au>
Date:   Sun Feb 24 07:25:29 2013 +0900

    MEDIUM: Move result element to struct check
    
    Move result element from struct server to struct check
    This allows check results to be independent of the check's server.
    
    This is in preparation for associating a agent check
    with a server which runs as well as the server's existing check.
    
    Signed-off-by: Simon Horman <ho...@verge.net.au>

Notes:
    OK.

commit f0d5a3c54696b4abd284b363adfb616cad0837ff
Author: Simon Horman <ho...@verge.net.au>
Date:   Sat Feb 23 15:35:38 2013 +0900

    MEDIUM: Paramatise functions over the check of a server
    
    Paramatise the following functions over the check of a server
    
    * set_server_down
    * set_server_up
    * srv_getinter
    * server_status_printf
    * set_server_check_status
    * set_server_disabled
    
    Generally the server parameter of these functions has been removed.
    Where it is still needed it is obtained using check->server.
    
    This is in preparation for associating a agent check
    with a server which runs as well as the server's existing check.
    By paramatising these functions they may act on each of the checks
    without further significant modification.
    
    Signed-off-by: Simon Horman <ho...@verge.net.au>
    
    ---
    
    This is a rather large patch and I would be happy to split it up
    on request.
    
    v4
    * Use check->type in process_check()
    
      Use check->type instead of s->proxy->options2 & PR_O2_CHK_ANY
      as the former is specific to the check being processed whereas
      the latter relates only to the primary check of a server.
    
    * Add type to struct check
    
      This is used to indicate the type of a check independent of
      its server's proxy's check type.
    
    v2 - v3
    * No Change

Notes:
    - still need to understand the SSP_O_HCHK -> check change
    - set_server_disabled() : takes a check arg, converts it to server then
      uses &s->check, seems suspicious or at least confusing (why not simply 
check ?)
    
    - also :
                    for(srv = s->tracknext; srv; srv = srv->tracknext)
    -                       set_server_disabled(srv);
    +                       set_server_disabled(&s->check);
    
           isn't it &srv->check instead ?
    
    - it's nice to have a check being the owner of a connection instead of the
      server, looks much cleaner than what we used to have.
    - it should probably be made it more obvious what case is covered by 
!check->type
      (if relevant at this point)

commit 8c7409c8a6ddb4f3629fd877935355e0902ebfa5
Author: Simon Horman <ho...@verge.net.au>
Date:   Sat Feb 23 15:14:19 2013 +0900

    MEDIUM: cfgparse: Factor out check initialisation
    
    This is in preparation for struct server having two elements
    of type struct check.
    
    Signed-off-by: Simon Horman <ho...@verge.net.au>
    
    ---
    
    v5
    * Remove server argument from init_check. It is not used.
    * Set type in init_check
    
      This allows a zero type to be used to indicate that
      a task for a secondary agent check should not be stated.

Notes:
    OK

commit 73f8958f7c982aa0d376ab5b6d4baeb0892a61c2
Author: Simon Horman <ho...@verge.net.au>
Date:   Sun Feb 24 17:23:38 2013 +0900

    MEDIUM: Add state to struct check
    
    Add state to struct check. This is currently used to store one bit,
    CHK_RUNNING, which is set if a check is running and clear otherwise.
    This bit was previously SRV_CHK_RUNNING of the state element of struct
    server.
    
    This is in preparation for associating a agent check
    with a server which runs as well as the server's existing check.
    
    Signed-off-by: Simon Horman <horms+rene...@verge.net.au>

Notes:
    Please use CHK_STATE_RUNNING instead of CHK_RUNNING so that it's
    easier to know it is related to the state attribute of the check.
    
    Also, we have many HCHK_* and now CHK_* as well, so I wonder how/when
    this will become confusing.

commit 8fe10dc6d602286db0270a0d1d27a3fa2907792e
Author: Simon Horman <ho...@verge.net.au>
Date:   Sun Feb 24 21:50:46 2013 +0900

    MEDIUM: Add name element to struct check
    
    This is in preparation for associating a agent check
    with a server which runs as well as the server's existing check.
    
    Signed-off-by: Simon Horman <horms+rene...@verge.net.au>
    
    ---
    
    v5
    * Rebase

Notes:
    Is it worth adding a name field just to report it in the stats ? Don't
    we have everything required to display the proper name when dumping
    the stats ? (maybe not).

commit 59d4d5ae53c2225a6001be9d526de6623dba0abd
Author: Simon Horman <ho...@verge.net.au>
Date:   Sun Feb 24 17:23:38 2013 +0900

    MEDIUM: Move health element to struct check
    
    This is in preparation for associating a agent check
    with a server which runs as well as the server's existing check.
    
    Signed-off-by: Simon Horman <ho...@verge.net.au>

Notes:
    OK

commit 4f7700d5da3c22444f16716d105e013ef69ad0b0
Author: Simon Horman <ho...@verge.net.au>
Date:   Sun Feb 24 20:50:33 2013 +0900

    MEDIUM: Add helper for task creation for checks
    
    This helper is in preparation for adding a second struct check element
    to struct server.
    
    Signed-off-by: Simon Horman <ho...@verge.net.au>
    
    ---
    
    v5
    * Rebase

Notes:
    Cosmetic, but the cfgparse change just changes the previous patch, so it 
could
    have been merged there.
    
    Please change the "polarity" of the start_check_task() function or make it
    very clear that it returns an error code, or change the check below :
    
    -          if (start_check_task(&s->check, mininter, nbcheck, srvpos++))
    +          if (start_check_task(&s->check, mininter, nbcheck, srvpos++) < 0)
                       return -1
    
    The problem is I'm reading it as "if we could start a check task, return 
-1".
    And yes, I know that all the kernel's networking code you're dealing with
    every day works this way so this can be confusing.
    
    Last cosmetic point, please keep srvpos++ out of the condition (I thought
    we lost it). I tend to discourage people from doing variable assignments
    in conditions because these are the places that are commented out the first
    during debugging sessions, causing the accidental loss of the assignment.
    
    Otherwise OK.

commit cf63f97ef6fa2ef584caab595c06738262f3ac80
Author: Simon Horman <ho...@verge.net.au>
Date:   Sat Feb 23 15:10:54 2013 +0900

    MEDIUM: checks: Add supplementary agent checks
    
    Allow an agent check to be run in conjunction with one other server
    health check.
    
    If the backend for a server check is not lb-agent-chk then an agent
    check may also be run using the agent-check parameter to a server,
    which sets the TCP port to be used for the agent check.
    
    e.g.
    server      web1_1 127.0.0.1:80 check agent-port 10000
    
    The agent-inter parameter may also be used to specify the interval
    and timeout for agent checks.
    
    If either the health or agent check determines that a server is down
    then it is marked as being down, otherwise it is marked as being up.
    
    Signed-off-by: Simon Horman <ho...@verge.net.au>
    
    ---
    
    v5
    * Rebase for removal of server argument from init_check
    * Rebase for setting of type in init_check
    
    v4
    *  Increment global.maxsock for agent-port.
    
       If agent-port is configured then an extra socket is required.
    
    * Do not send requests to secondary agent checks
    
      The request configuration of a proxy relates to the primary health
      check and should not be sent to the secondary health check if it
      is in operation.
    
    * Correct usage of PR_O2_LB_AGENT_CHK
    
      The correct way to check for PR_O2_LB_AGENT_CHK is
      not to use x & PR_O2_LB_AGENT_CHK, but rather to use
      (x & PR_O2_CHK_ANY ) == PR_O2_LB_AGENT_CHK.
    
    v2 - v3
    * No change

Notes:
    The commit message confused me but fortunately the doc fixed me :-)
    
    I'm having an issue with using agent-port to automatically enable the
    check. We've done this mistake with the stats in the past. Specifying
    any stats setting enables the stats. The end result is that nobody
    sets the stats URL or passwords in a defaults section.
    
    Here we'll get the same issue. On large deployments, it's very likely
    that users will want to have "default-server agent-port 10000" in their
    defaults section, but then they will have no way to disable it for some
    servers.
    
    Thus I'd rather stick to the same logic we have for current health checks
    which consists in having the port being an independant and harmless setting,
    and have an "agent-check" keyword on the server lines to enable it where
    relevant.
    
    Please do not forget to mention the compatibility between agent-port and
    default-server in the doc.
    
    Also, just a stupid question, we've introduced option lb-agent-chk very
    recently and we're still in development. Don't you think it would be
    useful to remove it now before a release if agent-check can cover all
    its needs ? It would avoid having to deal with complex setups in the
    future. CCing the lb.org guys here who most likely use it already (and
    might probably plan a config migration).

commit 8abb1b04fcb258a6004d37fe2dd2436cb121007a
Author: Simon Horman <ho...@verge.net.au>
Date:   Sun Mar 3 16:46:40 2013 +0900

    MEDIUM: Add helper for agent check events.
    
    Break agent check handling out of event_srv_chk_r().
    
    This is in preparation for supporting agent check results
    returned in an HTTP header.
    
    Signed-off-by: Simon Horman <ho...@verge.net.au>

Notes:
    OK

commit 77950728605ced6093a829b08ffc5b7d5ecc0b6d
Author: Simon Horman <ho...@verge.net.au>
Date:   Sun Mar 3 16:22:45 2013 +0900

    MEDIUM: Parser to allow matching of HTTP header
    
    Replace the current header parser, which simply skips the headers,
    with a version that allows matching of a key in a header.
    
    This is in preparation for supporting agent check results
    returned in an HTTP header.
    
    Signed-off-by: Simon Horman <ho...@verge.net.au>

Notes:
    I don't understand the parser :-( Some comments on the inputs/outputs of the
    function are probably needed since they're clearly not obvious.
    
    Also I fear that it does not support partial responses anymore, but I may
    be wrong (ie: wait for more data to come when the response is not complete).
    
    Anyway, this change must be tagged as MAJOR since it will definitely cause
    regressions in obscure places : I'm seeing the parser is stricter than it
    was, and people who implement script-based health checks tend to emit awful
    HTTP-like responses which certainly don't qualify as valid but which were
    accepted. So whatever we can do to optimise compatibility with previous
    checks should be considered (especially since we're speaking about checks
    and not production traffic).

commit 0b829e506657e0d18cc8ffd64808f8cb0e379168
Author: Simon Horman <ho...@verge.net.au>
Date:   Sun Mar 3 17:50:39 2013 +0900

    MEDIUM: Add http-check agent-hdr option
    
    Allow agent checks to obtain information in
    an HTTP header of the response to an http check.
    
    Signed-off-by: Simon Horman <ho...@verge.net.au>
    
    ---
    
    v4
    * Do not duplicate code that is in process_result()
    
    v2 - v3
    * No change

Notes:
    OK in principle, but what does it do when agent-port is set ?
    Is there any conflict or do we face a race between the two competing
    checks ?
    
    In the doc :
    
     http-check agent-hdr
       Use the value of the given http header as the result of an agent check
       May be used in sections :   defaults | frontend | listen | backend
                                     yes   |    no    |   yes  |   yes
       Arguments :
    
         <header>  The header string to use to send the server name
    
    Please mention "<header>" on the syntax line itself :
    
     http-check agent-hdr <header>

commit 410090bf97c2553da33f799c6dc313fb91b13ead
Author: Simon Horman <ho...@verge.net.au>
Date:   Wed Jun 5 18:06:07 2013 +0900

    MEDIUM: Add DRAIN state and report it on the stats page
    
    Add a DRAIN sub-state for a server which
    will be shown on the stats page instead of UP if
    an agent check is in use and the agent has most recently returned "drain".
    
    Signed-off-by: Simon Horman <ho...@verge.net.au>

Notes:
    In stats_dump_sv_stats() we use 'state' to display a new state, but the
    CSS is not updated, so we'll end up with any formating or colorset. I
    think it would be good to use :
      - the same color as "UP 2/3" (yellow) for "DRAIN 2/3"
      - a light brown such as #CC9900 when the DRAIN is in effect
    
    Also please update the comments at the top of the function to reflect
    the new input range.

commit 5a53bc5b4aebbfb499b96a5d3dadde514d885aaf
Author: Simon Horman <ho...@verge.net.au>
Date:   Wed Jun 26 23:38:56 2013 +0900

    MEDIUM: Log agent fail, stopped or down as info
    
    In the case where an agent check returns fail, stopped or down,
    log this as info when logging the server status along with any
    trailing message returned by the agent after fail, stopped or down.
    
    Previously only the trailing message was logged as info and
    if omitted no info was logged.
    
    Signed-off-by: Simon Horman <ho...@verge.net.au>

Notes:
    OK

commit 5ab56ee1510abfc79ec1f46657a49abb47da6824
Author: Simon Horman <ho...@verge.net.au>
Date:   Wed Jun 5 18:05:05 2013 +0900

    MEDIUM: Do not mark a server as down if the agent is unavailable
    
    In the case where agent-port is used and the agent
    check is a secondary check to not mark a server as down
    if the agent becomes unavailable.
    
    In this configuration the agent should only cause a server to be marked
    as down if the agent returns "fail", "stopped" or "down".
    
    Signed-off-by: Simon Horman <ho...@verge.net.au>
    
    ---
    
    v4
    * Never update health of agent on failure to connect
    
      Previously the health was recharged on such cases.
      But this causes the health to be recharged even
      if the most recent result from the agent was "fail", "stopped", or "down".
    
      The result was unnecessary logging of "fail", "stopped", or "down"
      results from the agent if they were interleaved with timeouts.
      Or in other words, if the agent responded only occasionally
      but consistently with "fail", "stopped", or "down".
    
    v3
    * No change
    
    v2
    * Only log agent server status if the change in status
      will affect the server's state

Notes:
    While I absolutely agree with the goal described in the commit message,
    I fail to connect it to what I'm seeing in the code. I don't know if it
    is a result of the rework of the patches but for me all it does it apply
    a second DRAIN state whose purpose I don't understand. I'm seeing that
    we first set WILLDRAIN, then update the status, then add DRAIN on top of
    that, that remains unclear to me. I'm not sure what situation the 4
    combinations of these flags correspond to.

commit 3980cce19837da833cf0c5ced030060257b9df0c
Author: Simon Horman <ho...@verge.net.au>
Date:   Thu Jun 27 21:15:04 2013 +0900

    MEDIUM: Set rise and fall of agent checks to 1
    
    This is achieved by moving rise and fall from struct server to struct check.
    
    After this move the behaviour of the primary check, server->check is
    unchanged. However, the secondary agent check, server->agent now has
    independent rise and fall values each of which are set to 1.
    
    The result is that receiving "fail", "stopped" or "down" just once from the
    agent will mark the server as down. And receiving a weight just once will
    allow the server to be marked up if its primary check is in good health.
    
    This opens up the scope to allow the rise and fall values of the agent
    check to be configurable, however this has not been implemented at this
    stage.
    
    Signed-off-by: Simon Horman <ho...@verge.net.au>
    
    ---
    
    v7
    When checking health against rise in set_server_up the health of a check
    should be checked against the rise of the same check. Otherwise the 
condition
    for the s->agent may be false when it should be true as s->agent's rise and
    thus healthy health value is 1 whereas the default rise for check is likely 
to
    be 3, as check may be s->check and the the default value for s->check.rise 
is 3.
    
    v5
    * Rebase

Notes:
    One remaining "server" below :
    
    -       int health;                             /* 0 to server->rise-1 = 
bad;
    -                                                * rise to 
server->rise+server->fall-1 = good */
    +       int health;                             /* 0 to rise-1 = bad;
    +                                                * rise to 
rise+server->fall-1 = good */
    +       int rise, fall;                         /* time in iterations */
    
    Otherwise OK.

commit fa2d91c61ce78d24143a74508d1dc8c85fca53f1
Author: Simon Horman <ho...@verge.net.au>
Date:   Sat Jun 22 14:36:39 2013 +0900

    MEDIUM: Add set agent pause|unpause unix socket command
    
    The syntax of this new command is:
    
    set agent <backend>/<server> pause|unpause
    
    This command changes the behaviour of agent checks as follows:
    
    In the case where an agent check is being run as a secondary check,
    due to the agent-port parameter of a server directive, new checks
    are only initialised when the agent is in the unpaused state. Thus,
    setting the agent to pause will prevent any new agent checks from
    begin initiated until the agent is set to unpaused.
    
    When set pause is in effect the processing of an agent check run as the
    primary check, due to either option lb-agent-check or http-check
    agent-hdr being set, or processing of a secondary agent check that was
    initiated while the agent was set as unpaused is as follows: All results
    that would alter the weight, specifically "drain" or a weight returned by
    the agent, are ignored. The processing of agent check is otherwise
    unchanged.
    
    The motivation for this option is to allow weight setting is to allow the
    weight changing effects of the agent checks to be paused to allow the
    weight of a server to be configured using set weight without being
    overridden by the agent.
    
    The default state is unpaused.
    
    Signed-off-by: Simon Horman <ho...@verge.net.au>

Notes:
    I think that instead of setting the agent status to pause/unpaused, we'd
    rather reuse the same principle as we currently have with servers :
    
         enable agent <backend>/<server>
         disable agent <backend>/<server>
    
    OK for the rest of course.

commit e4cbb6e2d82ad7d037316ab0dc4932e16a3b4e14
Author: Simon Horman <ho...@verge.net.au>
Date:   Tue Mar 13 14:02:40 2012 +0900

    MEDIUM: Break out check establishment into establish_chk()
    
    This is in preparation for adding a new type of check that
    uses a process rather than a socket.
    
    Signed-off-by: Simon Horman <ho...@verge.net.au>
    
    ---
    
    v4
    * Use check->type in establish_conn_chk()
    
      Use check->type instead of s->proxy->options2 & PR_O2_CHK_ANY
      as the former is specific to the check being processed whereas
      the latter relates only to the primary check of a server.
    
    v2 - v3
    * No change

Notes:
    I'd rather call it connect_chk() since we already use the verb
    "connect" at other places for the same purpose.

commit 23bc14cb0389d6ecb525c76766181ef01938a6cf
Author: Simon Horman <ho...@verge.net.au>
Date:   Tue Mar 13 14:03:22 2012 +0900

    MEDIUM: Add external check
    
    Add an external check which makes use of an external process to
    check the status of a server.
    
    ---
    
    v6
    * Correct implementation and documentation of arguments to external-check
      command so that they are consistent with both each other and ldirectord's
      external check. The motivation being to allow the same scripts to be used
      with both haproxy and ldirectord.
    
    v5
    * Rebase
    
    v4
    * Remove stray use of s->check in process_chk()
      The check parameter should be used throughout process_chk()
    * Layer 7 timeouts of agent checks should be ignored
    * Ensure that argc is never used uninitialised in prepare_external_check()
    
    v3
    * Rebase: basically a rewrite of large sections of the code
    * Merge with the following patches
      + "external-check: Actually execute command"
      + "Allow selection of of external-check in configuration file"
    
    v2
    * If the external command exits normally (WIFEXITED()) is true)
      then set the check's code to the exit status (WEXITSTATUS())
      of the process.
    * Treat a timeout is a failure case rather than the test having passed
    * Remove duplicate getnameinfo() call in start_checks()
    * Remove duplicate assignment of sockaddr argument to getnameinfo(9
      which caused the check port and check addr configuration of
      a server to be ignored.

Notes:
    Problems :
      - don't use "option xxx <arg>" despite the old poor choice introduced
        with "option httpchk". Options are meant to be booleans.
      - we need some way to ensure that we can globally disable this feature
        or better, that it must be explicitly enabled, as it introduces a
        major security risk (APIs, ...)
      - probably that we need to have a global prefix path setting for all
        commands.
      - anonymous union does not build with gcc-2.95 (still supported)
      - please don't use stdbool (again), it is not portable and has already
        broke twice in the past.
      - getnameinfo is not portable either, better use str2sa() or equivalent
        (and remove include netdb)
      - I'm quite worried about the changes with has_conn in process_chk,
        they're touching a very sensible place, so I think it would be
        much better to have a distinct process_chk function for external
        checks (we can even rename process_chk to process_chk_conn)

--------


Reply via email to