Opened 6 years ago

Closed 5 years ago

#3400 closed task (complete)

Modify Kea6 to read configuration from JSON file

Reported by: tomek Owned by: tomek
Priority: medium Milestone: Kea0.9
Component: dhcp6 Version:
Keywords: Cc:
CVSS Scoring: Parent Tickets:
Sensitive: no Defect Severity: N/A
Sub-Project: DHCP Feature Depending on Ticket:
Estimated Difficulty: 0 Add Hours to Ticket: 2
Total Hours: 72 Internal?: no

Description

Currently Kea6 receives configuration over control session from BIND10 framework. This task is about having the ability to get configuration from a different source, i.e. read it from a JSON file.

For testing purposes, it would be beneficial if the old capability were still available, but disabled. Compilation option seems reasonable here.

In the long run, it would be good to have the capability to support multiple configuration backends, even if we decide to always support only one. We know that OEMs and power users have their own configuration backends, e.g. LDAP.

Subtickets

Change History (14)

comment:1 Changed 6 years ago by tomek

  • Owner set to tomek
  • Status changed from new to assigned

comment:2 Changed 5 years ago by tomek

  • Owner changed from tomek to UnAssigned
  • Status changed from assigned to reviewing

Ticket is ready for review. This ticket covers a bit more than initially anticipated:

  • There is now --with-kea-config parameter to configure script. It allows selecting configuration backend: BIND10 (using old BIND10 framework as Kea 0.8) or JSON (using file based approach as Kea 0.9 will use)
  • The initalization was refactored. There's a separate Daemon class that is expected to be a base class for Dhcpv4Srv, Dhcpv6Srv and its D2 equivalent.
  • There are 2 separate implementations for ControlledDhcpv6Srv class, one for each configuration backend. Only one of those is compiled and linked.
  • Support for simple comments in JSON files has been added (# in the first column)
  • Logger is now initialized in the backend. JSON initialization is just a stub for now. It prints out all logs to stdout. There's a separate ticket for that: #3427.
  • Updated User's and Developer's Guide.
  • Added new directory with config examples (just one file for now)

Proposed ChangeLog:

7XX.	[func]*		tomek
	b10-dhcp6: New parameter added to configure: --with-kea-config.
	It allows to select configuration backend and accepts one of two
	values: BIND10, which uses BIND10 framework as Kea 0.8 did, or
	JSON, which reads configuration from an extended JSON file (i.e.
	regular JSON with comments).
	(Trac #3400, git TBD)

comment:3 Changed 5 years ago by tomek

  • Add Hours to Ticket changed from 0 to 32
  • Total Hours changed from 0 to 32

comment:4 Changed 5 years ago by tmark

  • Owner changed from UnAssigned to tmark

comment:5 Changed 5 years ago by jreed

For the changelog entry maybe also mention -- if applicable -- what the default behavior is and what the user may need to do if the default changes their previous startup.

comment:6 follow-up: Changed 5 years ago by tmark

While I see value in work you have here, it should not have been done prior to the design
called for in Trac #3398. That needs to be done before any of this work. We need a design first. Without a design we are liable to do work only to redo it later.

I would not recommend we move forward on this ticket until then.

What follows are some general thoughts and comments for going forward:


Providing alternative forms of configuration, such as from XML or LDAP is a
great idea but will involve a good deal of work and requires proper design.
The concept of using a compilation switch to temporarily support either BIND10
participation or file-only behavior is just clouding the waters with throw-away work. I do not see any real benefit from this. When 0.9 is done, there is
done BIND10 participation.

Having said that and while the internals of Session IO become obsolete with
the removal of BIND10, the construct of a "command socket" does not. Our long
range plan is provide some form of two interaction, if we're smart we can get
there relatively easily.

What the Session structure provides is a mechanism through which we can
asynchronously receive arbitrary commands, process them with callbacks, and
optionally return outcomes. A lot of the basic structure of this could be
retained, we simply replumb it internally so it is not based on BIND10 message
queue, rather it just a socket on which to listen and respond.

What I'm getting at is rather than make it a conditional compilation, first
augment what we have with a "command" to load the configuration from file.
This handler would more or less do what's in ControlledDhcpv6Srv::init() now.
Actually what it should do is fetch the configuration from file then pass that
to the existing configuration handler.

Upon startup, the controller simply invokes this handler directly with a
file name from the command line.

To reload via a signal handler, you could just set a flag (or build a command
message) that can be tested if "select" is interrupted and then invoke the
configuration file command handler.

Whether or not we open up a command channel (formerly session), becomes a
command line and/or configuration value. For now, it is simply turned off
until we replumb it.

My point is that without design, we are just throwing it together. We need
to work smarter here.


lib/cc/data already handles reading config text from a file. It would need
to be modified to deal with comments but if we want meaningful line numbers
in error messages it would have need to be done here rather than passing this
code comment-free text.

Secondly, our servers are likely not the only thing we will want to be able
to read (and possibly write) such files, so burying it inside Daemon, I think
is short-sighted.


Logging initialization for BIND10-less operation ought to be done in the
lib/logging. We already have a common library for logging behavior, so unless
we plan on replacing this it would make more sense to alter this library to
support a BIND10-less initialization directly, rather than in the new Daemon
class.


I'm guessing you haven't needed to at how the D2 controller/process is
structured. It sits upon a set of abstract classes (@section d2CPL Controllable

Process Layer (CPL)) I developed after looking at what DHCPv4 and v6 have in

common now. These classes are already positioned to do a lot of what we are
looking to do long term. And while they were built around BIND10, they can
be easily refitted.

It would be worth a look before we start going down a refactor path based on
Daemon. These are discussed in the developer's guide under D2 now.

I'm not saying Daemon isn't the way to go, on the contrary, it makes perfect
sense for all our servers to use a common core for this. It is what CPL is
designed to provide.

However, I don't think 0.9 is the time to refactor all this. I believe we can
position ourselves for where we want to be without a major overhaul.

comment:7 Changed 5 years ago by tmark

  • Add Hours to Ticket changed from 32 to 4
  • Owner changed from tmark to tomek
  • Total Hours changed from 32 to 36

comment:8 in reply to: ↑ 6 Changed 5 years ago by tomek

  • Add Hours to Ticket changed from 4 to 16
  • Owner changed from tomek to tmark
  • Total Hours changed from 36 to 52

Replying to tmark:

While I see value in work you have here, it should not have been done prior to the design
called for in Trac #3398. That needs to be done before any of this work. We need a design first. Without a design we are liable to do work only to redo it later.

I would not recommend we move forward on this ticket until then.

#3398 was discussed on kea-dev, some comments received, then described in dev guide and reviewed.
The design is now considered sufficiently documented and the ticket was closed.

What follows are some general thoughts and comments for going forward:


Providing alternative forms of configuration, such as from XML or LDAP is a
great idea but will involve a good deal of work and requires proper design.
The concept of using a compilation switch to temporarily support either BIND10
participation or file-only behavior is just clouding the waters with throw-away
work. I do not see any real benefit from this. When 0.9 is done, there is
done BIND10 participation.

I'm not 100% sure about that. It may be more complex than we initially thought.
We'll get rid of all Python code, that's for sure. But Bundy guys asked us whether it would
be possible to run Kea as a module in the Bundy framework. So they essentially are thinking
about picking Kea code and integrate it with their releases. I'm not sure whether that
makes sense or not. We'll have a discussion about this with Bundy team next week.
The point is that it may be possible that we'll decide to keep the capability to open up
a session socket, as we did in BIND10.

Having said that and while the internals of Session IO become obsolete with
the removal of BIND10, the construct of a "command socket" does not. Our long
range plan is provide some form of two interaction, if we're smart we can get
there relatively easily.

Agree.

What I'm getting at is rather than make it a conditional compilation, first
augment what we have with a "command" to load the configuration from file.

No, we need conditional compilation. For at least couple reasons:

  1. logger initialization is done differently (for Bundy framework, there is an init module

that will do that for us, in JSON file backend we need to do it ourselves)

  1. I think that when not using Bundy framework, we can have slightly smaller list

of libs we are linking with.

This handler would more or less do what's in ControlledDhcpv6Srv::init() now.
Actually what it should do is fetch the configuration from file then pass that
to the existing configuration handler.

I've restructured the code and I hope it's much better now. There is ControlledDhcpv6Srv class
that has all the handlers for config updates and for all commands. There is very small
subset of backend-specific implementations that is using those handlers. See
bin/dhcp6/{bundy|jsonfile}_backend.cc.

Upon startup, the controller simply invokes this handler directly with a
file name from the command line.

In particular, the JSON file backend processes config as you suggested: it passes a control
command "reload-config" with config file attached as parameter.

To reload via a signal handler, you could just set a flag (or build a command
message) that can be tested if "select" is interrupted and then invoke the
configuration file command handler.


lib/cc/data already handles reading config text from a file. It would need
to be modified to deal with comments but if we want meaningful line numbers
in error messages it would have need to be done here rather than passing this
code comment-free text.

No, it didn't. But I refactored that part. There is a new method called Element::fromJSONFile().
It does what you described here.

Secondly, our servers are likely not the only thing we will want to be able
to read (and possibly write) such files, so burying it inside Daemon, I think
is short-sighted.

That's why I thought that having a generic read a file method would be useful.
I did as you suggested and we now have a method that can read only JSON file and
create Element objects out of them.


Logging initialization for BIND10-less operation ought to be done in the
lib/logging. We already have a common library for logging behavior, so unless

No. What we need here is a method that receives a collection of Element objects, will
traverse them and based on that content it will call methods available in lib/log.
It is yet to be decided during #3427 where this method will be placed.

Had we do what you proposed, we would stuff JSON elements into lib/log. That's NOT something
we wanna do for at least 2 reasons. First, it would add extra dependency for liblog which is
supposed to be used everywhere. Second, lib/log would require lib/cc and lib/cc would require
lib/log, so you'd get an ugly circular dependency. Good luck with successfully building
unit-tests for those.


I'm guessing you haven't needed to at how the D2 controller/process is
structured. It sits upon a set of abstract classes (@section d2CPL Controllable

Process Layer (CPL)) I developed after looking at what DHCPv4 and v6 have in

common now. These classes are already positioned to do a lot of what we are
looking to do long term. And while they were built around BIND10, they can
be easily refitted.

It would be worth a look before we start going down a refactor path based on
Daemon. These are discussed in the developer's guide under D2 now.

I'm not saying Daemon isn't the way to go, on the contrary, it makes perfect
sense for all our servers to use a common core for this. It is what CPL is
designed to provide.

These are fair points. I looked a bit at D2Controller and several other classes.
In particular, I like the interface and calls like launch(argc, argv). It's much cleaner than
the stuff in Kea4/Kea6. I agree that the ultimate solution will be to have something
between Daemon and DControllerBase. I think there are some superfluous elements (in the sense
that they are D2 specific and will not be useable in Kea4/6).

However, I don't think 0.9 is the time to refactor all this. I believe we can
position ourselves for where we want to be without a major overhaul.

I decided to keep the Daemon class, but it is bare bones for now. It has no code in it.
The daemon.cc is there, but it's just a skeleton. That will make the merge with DControllerBase
rather easy task.

Ok, I'm brave enough to go ahead with another review attempt.

comment:9 follow-up: Changed 5 years ago by tmark

  • Add Hours to Ticket changed from 16 to 4
  • Owner changed from tmark to tomek
  • Total Hours changed from 52 to 56

General:


First, let me thank you for taking my prior comments constructively and
seeing some value in them.


Since you feel compelled to stick with the conditional compilation then
I have the comments:

I really think you should rename the configuration switch and
its description. This switch dictates whether or not Kea components
are compiled to be started and managed by BIND10. When built
this way, they will not function unless BIND10 is running.
Whether it is a BIND10 module or not, it still requires the JSON
configuration parsing library and parsers.

Therefore, it is inaccurate to describe the switch as selecting between
configuration mechanisms. It should be called something like --as-bundy-module
and described for what it actually does do. We should also consider documenting
it as experimental and subject to deprecation. I believe that maintaining
"Bundy-ability" is going to be problematic but that can be argued over later.

Supporting multiple modes of configuration is a great idea but building
the information models (i.e. class instances of subnets, pools, options...
that are created by parsers) from anything but JSON is going to require design
and an actual API as Stephen pointed out. Possibly as additional sets of parsers,
like fromXML or fromLDAP. And rather than being mutually exclusive at compile time,
they could be additive, just as the Database backends are now.

Instead of calling the files bundy_backend.cc and json_file_backend.cc, its really
more like bundy_controller.cc and kea_controller.cc, or bundy_ctl_impl.cc and
kea_ctl_impl.cc. Kea "controller" uses JSON file configuration as that's all we
have right now. Suppose down the road we build xml_config_parser.cc, what would
be different in the Kea "controller" class other than using fromXMLFile() intead of
fromJSONFile() method in init()?

Maybe these things seem petty, but naming things accurately is important. It will make
things far easier for others to understand and position us better for the future.


Now to actual code stuff:

Fix the copyright dates, several of the new files are wrong.
I know you've been planning this a long time but...


jsonfile_backend.cc

You should move this sanity check for the empty file name in init(), inside the
try-catch block, like this:

    try {
        // Basic sanity check: file name must not be empty.
        if (file_name.empty()) {
            isc_throw(BadValue, "JSON configuration file not specified");
        }

        // Read contents of the file and parse it as JSON
        json = Element::fromJSONFile(file_name, true);

        if (!json) {

That way the throw gets caught in the same catch and logged as any other config failure.


jsonfile_backend.cc

In Dameon::loggerInit(), using "TOP_BUILDDIR" won't work correctly once installed will it?
If I build it, install it and then delete the build tree, the path won't exist anymore.

    // Set a directory for creating lockfiles when running tests
    // @todo: Find out why this is needed. Without this, the logger doesn't
    // work.
    setenv("B10_LOCKFILE_DIR_FROM_BUILD", TOP_BUILDDIR, 1);

jsonfile_backend_unittest.cc

There should be test cases for failure scenarios:

1 - empty file name
2 - zero length and/or non-existant file
3 - no "Dhcp6" element
4 - Config file that contains Dhcp6 but has a content error so processCommand returns
a failed result


cc/data.cc

You need spaces around "?" operator here:

    return (fromJSON(preproc?preprocess(in):in, "<istream>", line, pos));

cc/data.cc

Element::preprocess()

Ok, not horrible for a first crack at it and I applaud your courage, but a static
replacement of the stream?

I think all you really need to do is this (I haven't tested this but it looks close):

    std::istream&
    preprocess(std::istream& in, int& line, int& pos) {
        // skip to first non-white space
        skipChars(in, WHITESPACE, line, pos);
        int c = in.peek();

        // if we're have comment skip to end of line
        while (c != EOF && c == '#") {
            // skip to end of the comment line
            while (c != EOF) {
                if (c == '\n') {
                    pos = 1;
                    ++line;
                }
                c = in.get();
            }

            // check next line
            skipChars(in, WHITESPACE, line, pos);
            c = in.peek();
        }

        return(in);
    }

This would eliminate the use of secondary stream altogether, make it thread safe,
and still update line and position.


cc/data/data_unittests.cc

Preprocessor test does not verify line and position values for the parsed elements.


cc/data.cc

The throw in fromJSONFile() should convert errno to the error string using strerror:

    if (!infile.is_open() {
        const char* error = strerror(errno);
        isc_throw(InvalidOperation, "Failed to read file " << file_name
                  << ",error: " << error);
    }


cc/tests/data_file_unittests.cc

readFileComments test has two lines commented out, but no explanation as to why:

   :
    writeFile(commented_content);

    // Check that the read will fail (without comment elimination)
//    EXPECT_THROW(Element::fromJSONFile(TEMP_FILE), JSONError);

    // Check that the read content is correct (with comment elimination)
    EXPECT_NO_THROW(Element::fromJSONFile(TEMP_FILE, true));
    //EXPECT_TRUE(exp->equals(*Element::fromJSONFile(TEMP_FILE, true)));
}

You have a cppcheck issue in main.cc:

<error file="src/bin/dhcp6/main.cc" line="108" id="variableScope" severity="style" msg="The scope of the variable &apos;status&apos; can be reduced."/>

CONFIG = BUNDY:

  • Builds and passed unit tests under OS-X
  • I installed this build and BIND10 was able to start Dhcp6 and alter its config via BINDCTL.

CONFIG = JSON

  • Builds and passed unit tests under OS-X
  • For grins, I installed b10-dhcp6 from this build and BIND10 fails to start it as one would expect:
2014-05-09 10:35:46.033 ERROR [kea.dhcp6/54575] DHCP6_INIT_FAIL failed to initialize Kea server: JSON configuration file not specified
Failed to initialize server: JSON configuration file not specified
2014-05-09 10:35:46.034 INFO  [b10-init.init/54568] BIND10_PROCESS_ENDED process 54575 of b10-dhcp6 ended with status 256
2014-05-09 10:35:46.035 ERROR [b10-init.init/54568] BIND10_COMPONENT_FAILED component b10-dhcp6 (pid 54575) failed: process exited normally with exit status 256


comment:10 in reply to: ↑ 9 ; follow-up: Changed 5 years ago by tomek

  • Add Hours to Ticket changed from 4 to 12
  • Owner changed from tomek to tmark
  • Total Hours changed from 56 to 68

Replying to tmark:

General:


First, let me thank you for taking my prior comments constructively and
seeing some value in them.

Don't mention it. That's how the review is supposed to work, right?



Since you feel compelled to stick with the conditional compilation then
I have the comments:

I really think you should rename the configuration switch and
its description. This switch dictates whether or not Kea components
are compiled to be started and managed by BIND10. When built
this way, they will not function unless BIND10 is running.
Whether it is a BIND10 module or not, it still requires the JSON
configuration parsing library and parsers.

Therefore, it is inaccurate to describe the switch as selecting between
configuration mechanisms. It should be called something like --as-bundy-module
and described for what it actually does do. We should also consider documenting
it as experimental and subject to deprecation. I believe that maintaining
"Bundy-ability" is going to be problematic but that can be argued over later.

No, because this is Bundy-ability is just a special case. If someone writes its own
configuration backend for LDAP, they will add capability to specify --with-kea-config=LDAP.
So there is only one parameter. If we defined --as-bundy-module, we'd have to add
such a parameter for each configuration backend.

Supporting multiple modes of configuration is a great idea but building
the information models (i.e. class instances of subnets, pools, options...
that are created by parsers) from anything but JSON is going to require design
and an actual API as Stephen pointed out. Possibly as additional sets of parsers,
like fromXML or fromLDAP. And rather than being mutually exclusive at compile time,
they could be additive, just as the Database backends are now.

True, but that is something so far in the future that I wouldn't worry about it.
Actually, my long term idea goes a bit further. Right now we have 2 sets of parsers.
The first one (in lib/cc) parse JSON text and create Element objects. Then we have
a second set of parsers (in src/bin/{d2,dhcp4,dhcp6} and src/lib/dhcpsrv) that walk
over a tree of Elements and eventually store configuration using CfgMgr? calls. I was
thinking that it would be possible to write a parser that would bypass the Element
step and immediately call CfgMgr? methods when parsing input file. In any case, that's
something we won't see anytime soon. And I agree that it would require an API definition.

Instead of calling the files bundy_backend.cc and json_file_backend.cc, its really
more like bundy_controller.cc and kea_controller.cc, or bundy_ctl_impl.cc and
kea_ctl_impl.cc. Kea "controller" uses JSON file configuration as that's all we

Neither name describes the functionality well, but I think "controller" will do the trick.
Renamed.

have right now. Suppose down the road we build xml_config_parser.cc, what would
be different in the Kea "controller" class other than using fromXMLFile() intead of
fromJSONFile() method in init()?

You could call XML scheme checker,XML preprocessor which could include files etc.
Or you could store that XML in some central repository. You never know what users will
come up with.

Maybe these things seem petty, but naming things accurately is important. It will make
things far easier for others to understand and position us better for the future.

Let's go ahead with the review/merge with what we have now. In the mean time I'll start
a discussion about best terminology to describe this functionality. If the decision is
to rename it, I'll happily do that.

Now to actual code stuff:

Fix the copyright dates, several of the new files are wrong.
I know you've been planning this a long time but...

Fixed. I hope I picked them all.



jsonfile_backend.cc

You should move this sanity check for the empty file name in init(), inside the
try-catch block, like this:

    try {
        // Basic sanity check: file name must not be empty.
        if (file_name.empty()) {
            isc_throw(BadValue, "JSON configuration file not specified");
        }

        // Read contents of the file and parse it as JSON
        json = Element::fromJSONFile(file_name, true);

        if (!json) {

That way the throw gets caught in the same catch and logged as any other config failure.

Done.


jsonfile_backend.cc

In Dameon::loggerInit(), using "TOP_BUILDDIR" won't work correctly once installed will it?
If I build it, install it and then delete the build tree, the path won't exist anymore.

    // Set a directory for creating lockfiles when running tests
    // @todo: Find out why this is needed. Without this, the logger doesn't
    // work.
    setenv("B10_LOCKFILE_DIR_FROM_BUILD", TOP_BUILDDIR, 1);

After a bit of discussion with Stephen, the code looks completely different. Hopefully
it is much simpler. TOP_BUILDDIR is not necessary anymore.


jsonfile_backend_unittest.cc

There should be test cases for failure scenarios:

1 - empty file name
2 - zero length and/or non-existant file
3 - no "Dhcp6" element
4 - Config file that contains Dhcp6 but has a content error so processCommand returns
a failed result

Added JSONFileBackendTest.configBroken. In the process, I discovered that our
config parser not throw if we pass a well formed JSON that is full of rubbish.
It will politely return non-zero status. Updated the code to detect that and
throw.


cc/data.cc

You need spaces around "?" operator here:

    return (fromJSON(preproc?preprocess(in):in, "<istream>", line, pos));

Done.



cc/data.cc

Element::preprocess()

Ok, not horrible for a first crack at it and I applaud your courage, but a static
replacement of the stream?

What? You never wrote code while experiencing nasty hangover? ;)

Ok, that was indeed ugly. The method is now thread-safe. Also, the method you
proposed below will not work. preprocess() command is supposed to walk through
the whole content and remove any comments.

I tried, but failed to implement this method doing stream in-situ replace. I thought
that it is similar to skipChars() implementation, but it isn't. The major difference
is that after skipChars() does its work, the whitespace characters are consumed and
will never be read again. preprocess() would have to selectively omit commented lines
while retaining the ability to read content BEFORE removed text. The only way to do this
that I'm aware of would be to use istream::unget() or istream::putback(). Both are hackish
and scary. Their documentation state that both operations can fail, even when used
properly.

The bottom line is that I decided to keep the replacement string, just pass it in
more sane way. I've created #3450 to improve that preprocess().

cc/data/data_unittests.cc

Preprocessor test does not verify line and position values for the parsed elements.

Added new Element.getPositionCommented test.



cc/data.cc

The throw in fromJSONFile() should convert errno to the error string using strerror:

    if (!infile.is_open() {
        const char* error = strerror(errno);
        isc_throw(InvalidOperation, "Failed to read file " << file_name
                  << ",error: " << error);
    }

Thanks. Fixed.


cc/tests/data_file_unittests.cc

readFileComments test has two lines commented out, but no explanation as to why:

   :
    writeFile(commented_content);

    // Check that the read will fail (without comment elimination)
//    EXPECT_THROW(Element::fromJSONFile(TEMP_FILE), JSONError);

    // Check that the read content is correct (with comment elimination)
    EXPECT_NO_THROW(Element::fromJSONFile(TEMP_FILE, true));
    //EXPECT_TRUE(exp->equals(*Element::fromJSONFile(TEMP_FILE, true)));
}

Oops. They are now uncommented and the test is (surprisingly) passing.


You have a cppcheck issue in main.cc:

<error file="src/bin/dhcp6/main.cc" line="108" id="variableScope" severity="style" msg="The scope of the variable &apos;status&apos; can be reduced."/>

Variable removed.

CONFIG = BUNDY:

  • Builds and passed unit tests under OS-X
  • I installed this build and BIND10 was able to start Dhcp6 and alter its config via BINDCTL.

CONFIG = JSON

  • Builds and passed unit tests under OS-X
  • For grins, I installed b10-dhcp6 from this build and BIND10 fails to start it as one would expect:
2014-05-09 10:35:46.033 ERROR [kea.dhcp6/54575] DHCP6_INIT_FAIL failed to initialize Kea server: JSON configuration file not specified
Failed to initialize server: JSON configuration file not specified
2014-05-09 10:35:46.034 INFO  [b10-init.init/54568] BIND10_PROCESS_ENDED process 54575 of b10-dhcp6 ended with status 256
2014-05-09 10:35:46.035 ERROR [b10-init.init/54568] BIND10_COMPONENT_FAILED component b10-dhcp6 (pid 54575) failed: process exited normally with exit status 256

Well, actually the error message should be more clear. It now explains that -c command line option
is mandatory. You can do something like:

./b10-dhcp6 -c ../../../doc/examples/kea6/several-subnets.json

to start it.

comment:11 Changed 5 years ago by tomek

Oh, I had to merge fixes from #3449 (Mac Os compilation fixes) to trac3400 branch. Hope you don't mind.

comment:12 in reply to: ↑ 10 Changed 5 years ago by tmark

  • Add Hours to Ticket changed from 12 to 2
  • Total Hours changed from 68 to 70

cc/data.cc

Element::preprocess()

There is a nice long comment at the beginning of this method explaining why
it returns a static. I think you can delete this comment now ;).

Other than that please merge your changes.

comment:13 Changed 5 years ago by tmark

  • Owner changed from tmark to tomek

comment:14 Changed 5 years ago by tomek

  • Resolution set to complete
  • Status changed from reviewing to closed
  • Total Hours changed from 70 to 72

Thanks a lot for the review. It was a long process, but the solution is now much better than initially planned. I also learned quite a few new things.

Note: See TracTickets for help on using tickets.