// used directly. It is intended to keep anything you may want to
// put there - comments, extra designations, floor or department
// names etc. These structures will be made available to Kea hooks.
- // You can define multiple user-contexts in the same scope without
- // the last one replacing previous values. A comment entry is
- // translated into a user-context with a "comment" property so
- // you can include comments inside the configuration itself.
+ // A comment entry is translated into a user-context with a
+ // "comment" property so you can include comments inside the
+ // configuration itself.
"subnet4": [
{
"pools": [ {
{
"name": "none"
},
- // Two comments (or user contexts) in the same scope are combined
- {
- "comment": "first comment",
- "comment": "second comment",
- "name": "two"
- },
- // Of course this applies to a comment and a user context too
+ // A comment and a user-context can be specified
{
"comment": "a comment",
"name": "both",
// In control socket (more for the agent)
"control-socket": {
- "comment": "REST API",
"socket-type": "unix",
"socket-name": "/tmp/kea4-ctrl-socket",
"user-context": { "comment": "Indirect comment" }
// structures. You can put anything you want in the user-context
// as long as it is a valid JSON and it starts with a map (i.e.
// is enclosed by curly brackets).
- // You can define multiple user-contexts in the same scope without
- // the last one replacing previous values. A comment entry is
- // translated into a user-context with a "comment" property so
- // you can include comments inside the configuration itself.
+ // A comment entry is translated into a user-context with a
+ // "comment" property so you can include comments inside the
+ // configuration itself.
"subnet6": [
{
"pools": [
{
"name": "none"
},
- // Two comments (or user contexts) in the same scope are combined
- {
- "comment": "first comment",
- "comment": "second comment",
- "name": "two"
- },
- // Of course this applies to a comment and a user context too
+ // A comment and a user-context can be specified
{
"comment": "a comment",
"name": "both",
// In control socket (more for the agent)
"control-socket": {
- "comment": "REST API",
"socket-type": "unix",
"socket-name": "/tmp/kea6-ctrl-socket",
"user-context": { "comment": "Indirect comment" }
<para>
User contexts can be specified on either global scope,
shared network, subnet, pool, client class, option data or
- definition level but not yet for a host reservation. One
- other useful usage is the ability to store comments or
- descriptions.
+ definition level, and host reservation. One other useful
+ usage is the ability to store comments or descriptions.
</para>
<para>
It should be noted that Kea will not use that information, but will
simply store and make it available to hook libraries. It is up to the
hook library to extract that information and make use of it.
- The parser translates "comment" entries into a user-context
- with the entry, this allows to attach comments inside the
+ The parser translates a "comment" entry into a user-context
+ with the entry, this allows to attach a comment inside the
configuration itself.
</para>
<para>
<para>
User contexts can be specified on either global scope,
shared network, subnet, pool, client class, option data or
- definition level but not yet for a host reservation. One
- other useful usage is the ability to store comments or
- descriptions.
+ definition level, and host reservation. One other useful
+ usage is the ability to store comments or descriptions.
</para>
<para>
it just stores it, making it available to the hook
libraries. It is up to each hook library to extract the information
and make use of it.
- The parser translates "comment" entries into a user-context
- with the entry, this allows to attach comments inside the
+ The parser translates a "comment" entry into a user-context
+ with the entry, this allows to attach a comment inside the
configuration itself.
</para>
<para>
arbitrary complexity. Kea does not use that data on its own, simply stores
and makes it available for the hook libraries.
</para>
- <para>
- Usually when an entry is defined multiple times in the same scope
- the last value is used overwriting previous values (this
- behavior will be fixed some time in the future). With user contexts values
- are combined at the first level, for instance multiple user context
- with a "comment" entry gives an entry with the list of accumulated
- values.
- </para>
<para>
Another use case for user contexts may be storing comments and other
information that will be retained by Kea. Regular comments are discarded
assert_str_eq "1.0" ${version} "Expected kea-admin to return %s, returned value was %s"
- # Ok, we have a 1.0 database. Let's upgrade it to 5.1
+ # Ok, we have a 1.0 database. Let's upgrade it to 6.0
${keaadmin} lease-upgrade mysql -u $db_user -p $db_password -n $db_name -d $db_scripts_dir
ERRCODE=$?
count=`echo $text | grep -ic "order by l\.address"`
assert_eq 1 $count "lease6DumpData doesn't have order by clause. (returned count %d, expected %d)"
+ #table: host_identifier_type (upgrade 4.1 -> 5.0)
# verify that host_identifier_type table exists.
qry="select count(*) from host_identifier_type";
count=`mysql_execute "${qry}"`
assert_eq 0 $ERRCODE "show create table hosts failed. (expected status code %d, returned %d)"
assert_eq 1 "$count" "show create table hosts did not return correct number of fk_host_identifier_type instances. (expected %d, returned %d)"
+ #table: dhcp_option_scope (upgrade 4.1 -> 5.0)
# verify that dhcp_option_scope table exists.
qry="select count(*) from dhcp_option_scope";
count=`mysql_execute "${qry}"`
assert_eq 0 $ERRCODE "select from dhcp_option_scope failed. (expected status code %d, returned %d)"
assert_eq 4 "$count" "dhcp_option_scope does not contain correct number of entries. (expected %d, returned %d)"
+ #table: scope_id columns to dhcp4_options (upgrade 4.1 -> 5.0)
# verify that dhcp4_options table includes scope_id
qry="select scope_id from dhcp4_options";
count=`mysql_execute "${qry}"`
ERRCODE=$?
assert_eq 0 $ERRCODE "select scope_id from dhcp4_options failed. (expected status code %d, returned %d)"
+ #table: scope_id columns to dhcp6_options (upgrade 4.1 -> 5.0)
# verify that dhcp6_options table includes scope_id
qry="select scope_id from dhcp6_options";
count=`mysql_execute "${qry}"`
ERRCODE=$?
assert_eq 0 $ERRCODE "select scope_id from dhcp6_options failed. (expected status code %d, returned %d)"
+ #table: DHCPv4 fixed field colums (upgrade 4.1 -> 5.0)
# verify that hosts table has columns holding values for DHCPv4 fixed fields
qry="select dhcp4_next_server, dhcp4_server_hostname, dhcp4_boot_file_name from hosts";
count=`mysql_execute "${qry}"`
count=`echo $text | grep -ic unsigned`
assert_eq 1 $count "dhcp6_subnet_id is not of unsigned type. (expected count %d, returned %d)"
- # Verify upgraded schema reports version 5.1
+ #host_identifier_type should have rows for types 3 and 4 (upgrade 5.0 -> 5.1)
+ qry="select count(*) from host_identifier_type";
+ count=`mysql_execute "${qry}"`
+ ERRCODE=$?
+ assert_eq 0 $ERRCODE "select from host_identifier_type failed. (expected status code %d, returned %d)"
+ assert_eq 5 "$count" "host_identifier_type does not contain correct number of entries. (expected count %d, returned %d)"
+
+ #table: user_context columns to hosts, dhcp4_options and dhcp6_options (upgrade 5.1 -> 6.0)
+ # verify that hosts table includes user_context
+ qry="select user_context from hosts";
+ count=`mysql_execute "${qry}"`
+ ERRCODE=$?
+ assert_eq 0 $ERRCODE "select user_context from hosts failed. (expected status code %d, returned %d)"
+
+ # verify that dhcp4_options table includes user_context
+ qry="select user_context from dhcp4_options";
+ count=`mysql_execute "${qry}"`
+ ERRCODE=$?
+ assert_eq 0 $ERRCODE "select user_context from dhcp4_options failed. (expected status code %d, returned %d)"
+
+ # verify that dhcp6_options table includes user_context
+ qry="select user_context from dhcp6_options";
+ count=`mysql_execute "${qry}"`
+ ERRCODE=$?
+ assert_eq 0 $ERRCODE "select user_context from dhcp6_options failed. (expected status code %d, returned %d)"
+
+ # Verify upgraded schema reports version 6.0
version=$(${keaadmin} lease-version mysql -u $db_user -p $db_password -n $db_name -d $db_scripts_dir)
- assert_str_eq "5.1" ${version} "Expected kea-admin to return %s, returned value was %s"
+ assert_str_eq "6.0" ${version} "Expected kea-admin to return %s, returned value was %s"
# Let's wipe the whole database
mysql_wipe
# Verify that kea-admin lease-version returns the correct version
version=$(${keaadmin} lease-version pgsql -u $db_user -p $db_password -n $db_name)
- assert_str_eq "3.2" ${version} "Expected kea-admin to return %s, returned value was %s"
+ assert_str_eq "4.0" ${version} "Expected kea-admin to return %s, returned value was %s"
# Let's wipe the whole database
pgsql_wipe
assert_eq 1 "$output" "lease_hwaddr_source does not contain entry for HWADDR_SOURCE_UNKNOWN. (record count %d, expected %d)"
}
-pgsql_upgrade_3_0_to_3_1() {
- # Verify upgraded schema reports version 3.1.
+pgsql_upgrade_3_0_to_4_0() {
+ # Verify upgraded schema reports version 4.0.
version=$(${keaadmin} lease-version pgsql -u $db_user -p $db_password -n $db_name -d $db_scripts_dir)
- assert_str_eq "3.1" ${version} "Expected kea-admin to return %s, returned value was %s"
+ assert_str_eq "4.0" ${version} "Expected kea-admin to return %s, returned value was %s"
}
pgsql_upgrade_test() {
# Check 2.0 to 3.0 upgrade
pgsql_upgrade_2_0_to_3_0
- # Check 3.0 to 3.1 upgrade
- pgsql_upgrade_3_0_to_3_1
+ # Check 3.0 to 4.0 upgrade
+ pgsql_upgrade_3_0_to_4_0
# Let's wipe the whole database
pgsql_wipe
user_context: USER_CONTEXT {
ctx.enter(ctx.NO_KEYWORD);
} COLON map_value {
- ctx.stack_.back()->combine_set("user-context", $4);
+ ElementPtr parent = ctx.stack_.back();
+ ElementPtr user_context = $4;
+ ConstElementPtr old = parent->get("user-context");
+ if (old) {
+ if ((old->size() != 1) || !old->contains("comment")) {
+ std::stringstream msg;
+ msg << "duplicate user-context entries (previous at "
+ << old->getPosition().str() << ")";
+ error(@1, msg.str());
+ }
+ user_context->set("comment", old->get("comment"));
+ }
+ parent->set("user-context", user_context);
ctx.leave();
};
comment: COMMENT {
ctx.enter(ctx.NO_KEYWORD);
-} COLON value {
- ElementPtr e(new MapElement(ctx.loc2pos(@1)));
- e->set("comment", $4);
- ctx.stack_.back()->combine_set("user-context", e);
+} COLON STRING {
+ ElementPtr parent = ctx.stack_.back();
+ ConstElementPtr old = parent->get("user-context");
+ if (old) {
+ old->set("comment", $4);
+ } else {
+ ElementPtr e(new MapElement(ctx.loc2pos(@1)));
+ e->set("comment", $4);
+ top->set("user-context", e);
+ }
ctx.leave();
};
control_socket_param: control_socket_type
| control_socket_name
- | control_socket_user_context
- | control_socket_comment
+ | user_context
+ | comment
| unknown_map_entry
;
ctx.leave();
};
-control_socket_user_context: user_context;
-
-control_socket_comment: COMMENT {
- ctx.enter(ctx.NO_KEYWORD);
-} COLON value {
- ctx.stack_.back()->combine_set("comment", $4);
- ctx.leave();
-};
-
// --- dhcp ddns ---------------------------------------------
dhcp_ddns: DHCP_DDNS {
user_context: USER_CONTEXT {
ctx.enter(ctx.NO_KEYWORD);
} COLON map_value {
- ctx.stack_.back()->combine_set("user-context", $4);
+ ElementPtr parent = ctx.stack_.back();
+ ElementPtr user_context = $4;
+ ConstElementPtr old = parent->get("user-context");
+ if (old) {
+ if ((old->size() != 1) || !old->contains("comment")) {
+ std::stringstream msg;
+ msg << "duplicate user-context entries (previous at "
+ << old->getPosition().str() << ")";
+ error(@1, msg.str());
+ }
+ user_context->set("comment", old->get("comment"));
+ }
+ parent->set("user-context", user_context);
ctx.leave();
};
comment: COMMENT {
ctx.enter(ctx.NO_KEYWORD);
-} COLON value {
- ElementPtr e(new MapElement(ctx.loc2pos(@1)));
- e->set("comment", $4);
- ctx.stack_.back()->combine_set("user-context", e);
+} COLON STRING {
+ ElementPtr parent = ctx.stack_.back();
+ ConstElementPtr old = parent->get("user-context");
+ if (old) {
+ old->set("comment", $4);
+ } else {
+ ElementPtr e(new MapElement(ctx.loc2pos(@1)));
+ e->set("comment", $4);
+ top->set("user-context", e);
+ }
ctx.leave();
};
control_socket_param: socket_type
| socket_name
- | socket_user_context
- | socket_comment
+ | user_context
+ | comment
| unknown_map_entry
;
ctx.leave();
};
-socket_user_context: user_context;
-
-socket_comment: COMMENT {
- ctx.enter(ctx.NO_KEYWORD);
-} COLON value {
- ctx.stack_.back()->combine_set("comment", $4);
- ctx.leave();
-};
-
// --- dhcp ddns ---------------------------------------------
dhcp_ddns: DHCP_DDNS {