From: Francis Dupont Date: Thu, 21 Jun 2018 23:05:09 +0000 (+0200) Subject: [5584] Checkpoint: core code and test done X-Git-Tag: trac5685_base~2^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=66f4a42a9b3fca8f9704ec406931f1f4a8ca4b50;p=thirdparty%2Fkea.git [5584] Checkpoint: core code and test done --- diff --git a/src/bin/admin/kea-admin.in b/src/bin/admin/kea-admin.in index 4be383ddb4..885d1a4765 100644 --- a/src/bin/admin/kea-admin.in +++ b/src/bin/admin/kea-admin.in @@ -490,9 +490,9 @@ cql_dump() { # Get the query appropriate to lease version. Explicitly specify all columns # so that they are returned in expected order. if [ $dump_type -eq 4 ]; then - dump_query="SELECT address,hwaddr,client_id,valid_lifetime,expire,subnet_id,fqdn_fwd,fqdn_rev,hostname,state FROM lease4" + dump_query="SELECT address,hwaddr,client_id,valid_lifetime,expire,subnet_id,fqdn_fwd,fqdn_rev,hostname,state,user_context FROM lease4" elif [ $dump_type -eq 6 ]; then - dump_query="SELECT address,duid,valid_lifetime,expire,subnet_id,pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,hwtype,hwaddr_source,state FROM lease6" + dump_query="SELECT address,duid,valid_lifetime,expire,subnet_id,pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,hwtype,hwaddr_source,state,user_context FROM lease6" else log_error "lease-dump: lease type ( -4 or -6 ) needs to be specified" usage diff --git a/src/bin/admin/tests/cql_tests.sh.in b/src/bin/admin/tests/cql_tests.sh.in index 0478fd87f8..082101ad9f 100644 --- a/src/bin/admin/tests/cql_tests.sh.in +++ b/src/bin/admin/tests/cql_tests.sh.in @@ -1,6 +1,6 @@ #!/bin/sh -# Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this @@ -40,11 +40,11 @@ cql_lease_init_test() { assert_eq 0 $? "schema_version table check failed, expected exit code: %d, actual: %d" # Check lease4 table - cql_execute "SELECT address, hwaddr, client_id, valid_lifetime, expire, subnet_id, fqdn_fwd, fqdn_rev, hostname, state FROM lease4;" + cql_execute "SELECT address, hwaddr, client_id, valid_lifetime, expire, subnet_id, fqdn_fwd, fqdn_rev, hostname, state, user_context FROM lease4;" assert_eq 0 $? "lease4 table check failed, expected exit code: %d, actual: %d" # Check lease6 table - cql_execute "SELECT address, duid, valid_lifetime, expire, subnet_id, pref_lifetime, lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, state FROM lease6;" + cql_execute "SELECT address, duid, valid_lifetime, expire, subnet_id, pref_lifetime, lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, state, user_context FROM lease6;" assert_eq 0 $? "lease6 table check failed, expected exit code: %d, actual: %d" # Check lease6_types table @@ -82,7 +82,7 @@ cql_lease_version_test() { # Verify that kea-admin lease-version returns the correct version. version=$($keaadmin lease-version cql -u $db_user -p $db_password -n $db_name) - assert_str_eq "2.0" $version "Expected kea-admin to return %s, returned value was %s" + assert_str_eq "3.0" $version "Expected kea-admin to return %s, returned value was %s" # Wipe the database. cql_execute_script $db_scripts_dir/cql/dhcpdb_drop.cql @@ -152,16 +152,16 @@ cql_lease4_dump_test() { # 1436173267 corresponds to 2015-06-06 11:01:07 insert_cql="\ INSERT INTO lease4(address, hwaddr, client_id, valid_lifetime, expire, subnet_id,\ - fqdn_fwd, fqdn_rev, hostname, state)\ + fqdn_fwd, fqdn_rev, hostname, state, user_context)\ VALUES(-1073741302,textAsBlob('20'),textAsBlob('30'),40,1430694930,50,true,true,\ - 'one.example.com', 0);\ + 'one.example.com', 0, '');\ INSERT INTO lease4(address, hwaddr, client_id, valid_lifetime, expire, subnet_id,\ - fqdn_fwd, fqdn_rev, hostname, state)\ - VALUES(-1073741301,NULL,textAsBlob('123'),40,1433464245,50,true,true,'', 1);\ + fqdn_fwd, fqdn_rev, hostname, state, user_context)\ + VALUES(-1073741301,NULL,textAsBlob('123'),40,1433464245,50,true,true,'', 1, '');\ INSERT INTO lease4(address, hwaddr, client_id, valid_lifetime, expire, subnet_id,\ - fqdn_fwd, fqdn_rev, hostname, state)\ + fqdn_fwd, fqdn_rev, hostname, state, user_context)\ VALUES(-1073741300,textAsBlob('22'),NULL,40,1436173267,50,true,true,\ - 'three.example.com', 2);" + 'three.example.com', 2, '');" cql_execute "$insert_cql" assert_eq 0 $? "insert into lease4 failed, expected exit code %d, actual %d" @@ -222,19 +222,19 @@ cql_lease6_dump_test() { insert_cql="\ INSERT INTO lease6(address, duid, valid_lifetime, expire, subnet_id,\ pref_lifetime, lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname,\ - hwaddr, hwtype, hwaddr_source, state)\ + hwaddr, hwtype, hwaddr_source, state, user_context)\ VALUES('2001:db8::10',textAsBlob('20'),30,1430694930,40,50,1,60,70,true,true,\ - 'one.example.com',textAsBlob('80'),90,16,0);\ + 'one.example.com',textAsBlob('80'),90,16,0,'');\ INSERT INTO lease6(address, duid, valid_lifetime, expire, subnet_id,\ pref_lifetime, lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname,\ - hwaddr, hwtype, hwaddr_source, state)\ + hwaddr, hwtype, hwaddr_source, state, user_context)\ VALUES('2001:db8::11',NULL,30,1433464245,40,50,1,60,70,true,true,\ - '',textAsBlob('80'),90,1,1);\ + '',textAsBlob('80'),90,1,1,'');\ INSERT INTO lease6(address, duid, valid_lifetime, expire, subnet_id,\ pref_lifetime, lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname,\ - hwaddr, hwtype, hwaddr_source, state)\ + hwaddr, hwtype, hwaddr_source, state, user_context)\ VALUES('2001:db8::12',textAsBlob('21'),30,1436173267,40,50,1,60,70,true,true,\ - 'three.example.com',textAsBlob('80'),90,4,2);" + 'three.example.com',textAsBlob('80'),90,4,2,'');" cql_execute "$insert_cql" assert_eq 0 $? "insert into lease6 failed, expected exit code %d, actual %d" diff --git a/src/bin/admin/tests/data/cql.lease4_dump_test.reference.csv b/src/bin/admin/tests/data/cql.lease4_dump_test.reference.csv index 5316f1e734..8da31db3ea 100644 --- a/src/bin/admin/tests/data/cql.lease4_dump_test.reference.csv +++ b/src/bin/admin/tests/data/cql.lease4_dump_test.reference.csv @@ -1,4 +1,4 @@ -address,hwaddr,client_id,valid_lifetime,expire,subnet_id,fqdn_fwd,fqdn_rev,hostname,state --1073741302,0x3230,0x3330,40,1430694930,50,True,True,one.example.com,0 --1073741301,null,0x313233,40,1433464245,50,True,True,,1 --1073741300,0x3232,null,40,1436173267,50,True,True,three.example.com,2 +address,hwaddr,client_id,valid_lifetime,expire,subnet_id,fqdn_fwd,fqdn_rev,hostname,state,user_context +-1073741302,0x3230,0x3330,40,1430694930,50,True,True,one.example.com,0, +-1073741301,null,0x313233,40,1433464245,50,True,True,,1, +-1073741300,0x3232,null,40,1436173267,50,True,True,three.example.com,2, diff --git a/src/bin/admin/tests/data/cql.lease6_dump_test.reference.csv b/src/bin/admin/tests/data/cql.lease6_dump_test.reference.csv index 63a966d137..5763429f4c 100644 --- a/src/bin/admin/tests/data/cql.lease6_dump_test.reference.csv +++ b/src/bin/admin/tests/data/cql.lease6_dump_test.reference.csv @@ -1,4 +1,4 @@ -address,duid,valid_lifetime,expire,subnet_id,pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,hwtype,hwaddr_source,state -2001:db8::12,0x3231,30,1436173267,40,50,1,60,70,True,True,three.example.com,0x3830,90,4,2 -2001:db8::11,null,30,1433464245,40,50,1,60,70,True,True,,0x3830,90,1,1 -2001:db8::10,0x3230,30,1430694930,40,50,1,60,70,True,True,one.example.com,0x3830,90,16,0 +address,duid,valid_lifetime,expire,subnet_id,pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,hwtype,hwaddr_source,state,user_context +2001:db8::12,0x3231,30,1436173267,40,50,1,60,70,True,True,three.example.com,0x3830,90,4,2, +2001:db8::11,null,30,1433464245,40,50,1,60,70,True,True,,0x3830,90,1,1, +2001:db8::10,0x3230,30,1430694930,40,50,1,60,70,True,True,one.example.com,0x3830,90,16,0, diff --git a/src/bin/admin/tests/data/mysql.lease4_dump_test.reference.csv b/src/bin/admin/tests/data/mysql.lease4_dump_test.reference.csv index f7e8c71128..0155cad0a3 100644 --- a/src/bin/admin/tests/data/mysql.lease4_dump_test.reference.csv +++ b/src/bin/admin/tests/data/mysql.lease4_dump_test.reference.csv @@ -1,4 +1,4 @@ -address,hwaddr,client_id,valid_lifetime,expire,subnet_id,fqdn_fwd,fqdn_rev,hostname,state -0.0.0.10,3230,3330,40,2015-01-01 01:15:30,50,1,1,one.example.com,default -0.0.0.11,,313233,40,2015-02-02 02:30:45,50,1,1,,declined -0.0.0.12,3232,,40,2015-03-03 11:01:07,50,1,1,three.example.com,expired-reclaimed +address,hwaddr,client_id,valid_lifetime,expire,subnet_id,fqdn_fwd,fqdn_rev,hostname,state,user_context +0.0.0.10,3230,3330,40,2015-01-01 01:15:30,50,1,1,one.example.com,default, +0.0.0.11,,313233,40,2015-02-02 02:30:45,50,1,1,,declined, +0.0.0.12,3232,,40,2015-03-03 11:01:07,50,1,1,three.example.com,expired-reclaimed, diff --git a/src/bin/admin/tests/data/mysql.lease6_dump_test.reference.csv b/src/bin/admin/tests/data/mysql.lease6_dump_test.reference.csv index 696a8919ca..92a003d8a7 100644 --- a/src/bin/admin/tests/data/mysql.lease6_dump_test.reference.csv +++ b/src/bin/admin/tests/data/mysql.lease6_dump_test.reference.csv @@ -1,4 +1,4 @@ -address,duid,valid_lifetime,expire,subnet_id,pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,hwtype,hwaddr_source,state -10,3230,30,2015-04-04 01:15:30,40,50,IA_TA,60,70,1,1,one.example.com,3830,90,HWADDR_SOURCE_REMOTE_ID,default -11,,30,2015-05-05 02:30:45,40,50,IA_TA,60,70,1,1,,3830,90,HWADDR_SOURCE_RAW,declined -12,3231,30,2015-06-06 11:01:07,40,50,IA_TA,60,70,1,1,three.example.com,3830,90,HWADDR_SOURCE_DUID,expired-reclaimed +address,duid,valid_lifetime,expire,subnet_id,pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,hwtype,hwaddr_source,state,user_context +10,3230,30,2015-04-04 01:15:30,40,50,IA_TA,60,70,1,1,one.example.com,3830,90,HWADDR_SOURCE_REMOTE_ID,default, +11,,30,2015-05-05 02:30:45,40,50,IA_TA,60,70,1,1,,3830,90,HWADDR_SOURCE_RAW,declined, +12,3231,30,2015-06-06 11:01:07,40,50,IA_TA,60,70,1,1,three.example.com,3830,90,HWADDR_SOURCE_DUID,expired-reclaimed, diff --git a/src/bin/admin/tests/data/pgsql.lease4_dump_test.reference.csv b/src/bin/admin/tests/data/pgsql.lease4_dump_test.reference.csv index c7a49034ff..b194fe6bba 100644 --- a/src/bin/admin/tests/data/pgsql.lease4_dump_test.reference.csv +++ b/src/bin/admin/tests/data/pgsql.lease4_dump_test.reference.csv @@ -1,4 +1,4 @@ -address,hwaddr,client_id,valid_lifetime,expire,subnet_id,fqdn_fwd,fqdn_rev,hostname,state -0.0.0.10,20,30,40,,50,1,1,one.example.com,default -0.0.0.11,,013233,40,,50,1,1,,declined -0.0.0.12,22,,40,,50,1,1,three.example.com,expired-reclaimed +address,hwaddr,client_id,valid_lifetime,expire,subnet_id,fqdn_fwd,fqdn_rev,hostname,state,user_context +0.0.0.10,20,30,40,,50,1,1,one.example.com,default, +0.0.0.11,,013233,40,,50,1,1,,declined, +0.0.0.12,22,,40,,50,1,1,three.example.com,expired-reclaimed, diff --git a/src/bin/admin/tests/data/pgsql.lease6_dump_test.reference.csv b/src/bin/admin/tests/data/pgsql.lease6_dump_test.reference.csv index fb42171456..c88ab9e67d 100644 --- a/src/bin/admin/tests/data/pgsql.lease6_dump_test.reference.csv +++ b/src/bin/admin/tests/data/pgsql.lease6_dump_test.reference.csv @@ -1,4 +1,4 @@ -address,duid,valid_lifetime,expire,subnet_id,pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,state,hwaddr,hwtype,hwaddr_source -10,20,30,,40,50,IA_TA,60,70,1,1,one.example.com,default,80,90,HWADDR_SOURCE_REMOTE_ID -11,,30,,40,50,IA_TA,60,70,1,1,,declined,80,90,HWADDR_SOURCE_RAW -12,21,30,,40,50,IA_TA,60,70,1,1,three.example.com,expired-reclaimed,80,90,HWADDR_SOURCE_DUID +address,duid,valid_lifetime,expire,subnet_id,pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,state,user_context,hwaddr,hwtype,hwaddr_source +10,20,30,,40,50,IA_TA,60,70,1,1,one.example.com,default,,80,90,HWADDR_SOURCE_REMOTE_ID +11,,30,,40,50,IA_TA,60,70,1,1,,declined,,80,90,HWADDR_SOURCE_RAW +12,21,30,,40,50,IA_TA,60,70,1,1,three.example.com,expired-reclaimed,,80,90,HWADDR_SOURCE_DUID diff --git a/src/bin/admin/tests/mysql_tests.sh.in b/src/bin/admin/tests/mysql_tests.sh.in index 85c1a9558f..89988bcf7b 100644 --- a/src/bin/admin/tests/mysql_tests.sh.in +++ b/src/bin/admin/tests/mysql_tests.sh.in @@ -258,7 +258,7 @@ mysql_upgrade_test() { 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 6.0 + # Ok, we have a 1.0 database. Let's upgrade it to 6.1 ${keaadmin} lease-upgrade mysql -u $db_user -p $db_password -n $db_name -d $db_scripts_dir ERRCODE=$? @@ -449,9 +449,30 @@ EOF # lease4/6_stats changes are tested separately - # Verify upgraded schema reports version 6.0 + #table: user_context to lease4 and lease6 (upgrade 6.0 -> 6.1) + # verify that lease4 table includes user_context + qry="select user_context from lease4"; + count=`mysql_execute "${qry}"` + ERRCODE=$? + assert_eq 0 $ERRCODE "select user_context from lease4 failed. (expected status code %d, returned %d)" + + # verify that lease6 table includes user_context + qry="select user_context from lease6"; + count=`mysql_execute "${qry}"` + ERRCODE=$? + assert_eq 0 $ERRCODE "select user_context from lease6 failed. (expected status code %d, returned %d)" + + #table: logs (upgrade 6.0 -> 6.1) + mysql -u$db_user -p$db_password $db_name >/dev/null 2>&1 <getType() != Element::map)) { + isc_throw(BadValue, "user context '" << user_context_ + << "' is not a JSON map"); + } } Lease4Ptr result(new Lease4(addr4, hwaddr, client_id_.data(), @@ -1424,8 +1426,10 @@ CqlLease6Exchange::retrieve() { ConstElementPtr ctx; if (!user_context_.empty()) { ctx = Element::fromJSON(user_context_); - isc_throw(BadValue, "user context '" << user_context_ - << "' is not a JSON map"); + if (!ctx ||(ctx->getType() != Element::map)) { + isc_throw(BadValue, "user context '" << user_context_ + << "' is not a JSON map"); + } } // Create the lease and set the cltt (after converting from the diff --git a/src/lib/dhcpsrv/lease.cc b/src/lib/dhcpsrv/lease.cc index b96613fe2d..6b50a3858f 100644 --- a/src/lib/dhcpsrv/lease.cc +++ b/src/lib/dhcpsrv/lease.cc @@ -545,7 +545,7 @@ Lease6::toText() const { << "State: " << statesToText(state_) << "\n"; if (getContext()) { - stream << "User context: " << getContext() << "\n"; + stream << "User context: " << getContext()->str() << "\n"; } return (stream.str()); @@ -566,7 +566,7 @@ Lease4::toText() const { << "State: " << statesToText(state_) << "\n"; if (getContext()) { - stream << "User context: " << getContext() << "\n"; + stream << "User context: " << getContext()->str() << "\n"; } return (stream.str()); diff --git a/src/lib/dhcpsrv/tests/csv_lease_file4_unittest.cc b/src/lib/dhcpsrv/tests/csv_lease_file4_unittest.cc index bac7f143e7..d5fafd3bc4 100644 --- a/src/lib/dhcpsrv/tests/csv_lease_file4_unittest.cc +++ b/src/lib/dhcpsrv/tests/csv_lease_file4_unittest.cc @@ -15,6 +15,7 @@ using namespace isc; using namespace isc::asiolink; +using namespace isc::data; using namespace isc::dhcp; using namespace isc::dhcp::test; using namespace isc::util; @@ -105,7 +106,7 @@ CSVLeaseFile4Test::writeSampleFile() const { "host.example.com,0,\n" "192.0.2.1,,a:11:01:04,200,200,8,1,1,host.example.com,0,\n" "192.0.3.15,dd:de:ba:0d:1b:2e:3e:4f,0a:00:01:04,100,100,7," - "0,0,,1,\n"); + "0,0,,1,{ \"foobar\": true }\n"); } // This test checks the capability to read and parse leases from the file. @@ -143,6 +144,7 @@ TEST_F(CSVLeaseFile4Test, parse) { EXPECT_TRUE(lease->fqdn_rev_); EXPECT_EQ("host.example.com", lease->hostname_); EXPECT_EQ(Lease::STATE_DEFAULT, lease->state_); + EXPECT_FALSE(lease->getContext()); } // Second lease is malformed - HW address is empty when state @@ -174,6 +176,8 @@ TEST_F(CSVLeaseFile4Test, parse) { EXPECT_FALSE(lease->fqdn_rev_); EXPECT_TRUE(lease->hostname_.empty()); EXPECT_EQ(Lease::STATE_DECLINED, lease->state_); + ASSERT_TRUE(lease->getContext()); + EXPECT_EQ("{ \"foobar\": true }", lease->getContext()->str()); } // There are no more leases. Reading should cause no error, but the returned @@ -216,11 +220,12 @@ TEST_F(CSVLeaseFile4Test, recreate) { checkStats(lf, 0, 0, 0, 1, 1, 0); } - // Create second lease, with non-NULL client id. + // Create second lease, with non-NULL client id and user context. lease.reset(new Lease4(IOAddress("192.0.3.10"), hwaddr1_, CLIENTID, sizeof(CLIENTID), 100, 60, 90, 0, 7)); + lease->setContext(Element::fromJSON("{ \"foobar\": true }")); { SCOPED_TRACE("Second write"); ASSERT_NO_THROW(lf.append(*lease)); @@ -235,7 +240,7 @@ TEST_F(CSVLeaseFile4Test, recreate) { "192.0.3.2,00:01:02:03:04:05,,200,200,8,1,1,host.example.com," "2,\n" "192.0.3.10,0d:0e:0a:0d:0b:0e:0e:0f,01:02:03:04,100,100,7,0," - "0,,0,\n", + "0,,0,{ \"foobar\": true }\n", io_.readFile()); } @@ -253,9 +258,9 @@ TEST_F(CSVLeaseFile4Test, mixedSchemaload) { // schema 2.0 record - has state "192.0.2.2,06:07:08:09:2a:bc,,200,200,8,1,1," "two.example.com,1\n" - // schema 2.0 record - has state + // schema 2.1 record - has state and user context "192.0.2.3,06:07:08:09:3a:bc,,200,200,8,1,1," - "three.example.com,2\n" + "three.example.com,2,{ \"foobar\": true }\n" ); // Open the lease file. @@ -283,6 +288,7 @@ TEST_F(CSVLeaseFile4Test, mixedSchemaload) { EXPECT_EQ("one.example.com", lease->hostname_); // Verify that added state is DEFAULT EXPECT_EQ(Lease::STATE_DEFAULT, lease->state_); + EXPECT_FALSE(lease->getContext()); } { @@ -302,6 +308,7 @@ TEST_F(CSVLeaseFile4Test, mixedSchemaload) { EXPECT_TRUE(lease->fqdn_rev_); EXPECT_EQ("two.example.com", lease->hostname_); EXPECT_EQ(Lease::STATE_DECLINED, lease->state_); + EXPECT_FALSE(lease->getContext()); } { @@ -321,6 +328,8 @@ TEST_F(CSVLeaseFile4Test, mixedSchemaload) { EXPECT_TRUE(lease->fqdn_rev_); EXPECT_EQ("three.example.com", lease->hostname_); EXPECT_EQ(Lease::STATE_EXPIRED_RECLAIMED, lease->state_); + ASSERT_TRUE(lease->getContext()); + EXPECT_EQ("{ \"foobar\": true }", lease->getContext()->str()); } } @@ -384,6 +393,7 @@ TEST_F(CSVLeaseFile4Test, downGrade) { EXPECT_TRUE(lease->fqdn_rev_); EXPECT_EQ("three.example.com", lease->hostname_); EXPECT_EQ(Lease::STATE_EXPIRED_RECLAIMED, lease->state_); + EXPECT_FALSE(lease->getContext()); } } diff --git a/src/lib/dhcpsrv/tests/csv_lease_file6_unittest.cc b/src/lib/dhcpsrv/tests/csv_lease_file6_unittest.cc index f35798d70b..74bda17ea5 100644 --- a/src/lib/dhcpsrv/tests/csv_lease_file6_unittest.cc +++ b/src/lib/dhcpsrv/tests/csv_lease_file6_unittest.cc @@ -15,6 +15,7 @@ using namespace isc; using namespace isc::asiolink; +using namespace isc::data; using namespace isc::dhcp; using namespace isc::dhcp::test; using namespace isc::util; @@ -107,7 +108,7 @@ CSVLeaseFile6Test::writeSampleFile() const { "2001:db8:2::10,01:01:01:01:0a:01:02:03:04:05,300,300,6,150," "0,8,0,0,0,,,1,\n" "3000:1::,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,0,200,8,0,2," - "16,64,0,0,,,1,\n"); + "16,64,0,0,,,1,{ \"foobar\": true }\n"); } // This test checks the capability to read and parse leases from the file. @@ -147,6 +148,8 @@ TEST_F(CSVLeaseFile6Test, parse) { EXPECT_TRUE(lease->fqdn_fwd_); EXPECT_TRUE(lease->fqdn_rev_); EXPECT_EQ("host.example.com", lease->hostname_); + EXPECT_EQ(Lease::STATE_DECLINED, lease->state_); + EXPECT_FALSE(lease->getContext()); } // Second lease is malformed - DUID is empty. @@ -178,6 +181,8 @@ TEST_F(CSVLeaseFile6Test, parse) { EXPECT_FALSE(lease->fqdn_fwd_); EXPECT_FALSE(lease->fqdn_rev_); EXPECT_TRUE(lease->hostname_.empty()); + EXPECT_EQ(Lease::STATE_DECLINED, lease->state_); + EXPECT_FALSE(lease->getContext()); } // Reading the fourth lease should be successful. @@ -201,6 +206,9 @@ TEST_F(CSVLeaseFile6Test, parse) { EXPECT_FALSE(lease->fqdn_fwd_); EXPECT_FALSE(lease->fqdn_rev_); EXPECT_TRUE(lease->hostname_.empty()); + EXPECT_EQ(Lease::STATE_DECLINED, lease->state_); + ASSERT_TRUE(lease->getContext()); + EXPECT_EQ("{ \"foobar\": true }", lease->getContext()->str()); } // There are no more leases. Reading should cause no error, but the returned @@ -260,6 +268,7 @@ TEST_F(CSVLeaseFile6Test, recreate) { 7, 150, 300, 40, 70, 10, false, false, "", HWAddrPtr(), 64)); lease->cltt_ = 0; + lease->setContext(Element::fromJSON("{ \"foobar\": true }")); { SCOPED_TRACE("Third write"); ASSERT_NO_THROW(lf.append(*lease)); @@ -274,7 +283,7 @@ TEST_F(CSVLeaseFile6Test, recreate) { "2001:db8:2::10,01:01:01:01:0a:01:02:03:04:05" ",300,300,6,150,0,8,128,0,0,,,0,\n" "3000:1:1::,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f," - "300,300,10,150,2,7,64,0,0,,,0,\n", + "300,300,10,150,2,7,64,0,0,,,0,{ \"foobar\": true }\n", io_.readFile()); } @@ -296,7 +305,12 @@ TEST_F(CSVLeaseFile6Test, mixedSchemaLoad) { // schema 3.0 record - has hwaddr and state "2001:db8:1::3,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:03," - "200,200,8,100,0,7,0,1,1,three.example.com,0a:0b:0c:0d:0e,1\n"); + "200,200,8,100,0,7,0,1,1,three.example.com,0a:0b:0c:0d:0e,1\n" + + // schema 3.1 record - has hwaddr, state and user context + "2001:db8:1::4,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:03," + "200,200,8,100,0,7,0,1,1,three.example.com,0a:0b:0c:0d:0e,1," + "{ \"foobar\": true }\n"); // Open the lease file. CSVLeaseFile6 lf(filename_); @@ -326,6 +340,7 @@ TEST_F(CSVLeaseFile6Test, mixedSchemaLoad) { EXPECT_FALSE(lease->hwaddr_); // Verify that added state is STATE_DEFAULT EXPECT_EQ(Lease::STATE_DEFAULT, lease->state_); + EXPECT_FALSE(lease->getContext()); } { @@ -351,6 +366,7 @@ TEST_F(CSVLeaseFile6Test, mixedSchemaLoad) { EXPECT_EQ("01:02:03:04:05", lease->hwaddr_->toText(false)); // Verify that added state is STATE_DEFAULT EXPECT_EQ(Lease::STATE_DEFAULT, lease->state_); + EXPECT_FALSE(lease->getContext()); } { @@ -375,6 +391,33 @@ TEST_F(CSVLeaseFile6Test, mixedSchemaLoad) { ASSERT_TRUE(lease->hwaddr_); EXPECT_EQ("0a:0b:0c:0d:0e", lease->hwaddr_->toText(false)); EXPECT_EQ(Lease::STATE_DECLINED, lease->state_); + EXPECT_FALSE(lease->getContext()); + } + + { + SCOPED_TRACE("Forth lease valid"); + EXPECT_TRUE(lf.next(lease)); + ASSERT_TRUE(lease); + + // Verify that the lease attributes are correct. + EXPECT_EQ("2001:db8:1::4", lease->addr_.toText()); + ASSERT_TRUE(lease->duid_); + EXPECT_EQ("00:01:02:03:04:05:06:0a:0b:0c:0d:0e:03", lease->duid_->toText()); + EXPECT_EQ(200, lease->valid_lft_); + EXPECT_EQ(0, lease->cltt_); + EXPECT_EQ(8, lease->subnet_id_); + EXPECT_EQ(100, lease->preferred_lft_); + EXPECT_EQ(Lease::TYPE_NA, lease->type_); + EXPECT_EQ(7, lease->iaid_); + EXPECT_EQ(0, lease->prefixlen_); + EXPECT_TRUE(lease->fqdn_fwd_); + EXPECT_TRUE(lease->fqdn_rev_); + EXPECT_EQ("three.example.com", lease->hostname_); + ASSERT_TRUE(lease->hwaddr_); + EXPECT_EQ("0a:0b:0c:0d:0e", lease->hwaddr_->toText(false)); + EXPECT_EQ(Lease::STATE_DECLINED, lease->state_); + ASSERT_TRUE(lease->getContext()); + EXPECT_EQ("{ \"foobar\": true }", lease->getContext()->str()); } } @@ -412,10 +455,10 @@ TEST_F(CSVLeaseFile6Test, downGrade) { "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname," "hwaddr,state,user_context,FUTURE_COL\n" - // schema 3.0 record - has hwaddr and state + // schema 3.1 record - has hwaddr, state and user context "2001:db8:1::3,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:03," - "200,200,8,100,0,7,0,1,1,three.example.com,0a:0b:0c:0d:0e,1,," - "BOGUS\n"); + "200,200,8,100,0,7,0,1,1,three.example.com,0a:0b:0c:0d:0e,1," + "{ \"foobar\": true },BOGUS\n"); // Open should succeed in the event someone is downgrading. CSVLeaseFile6 lf(filename_); @@ -448,6 +491,8 @@ TEST_F(CSVLeaseFile6Test, downGrade) { ASSERT_TRUE(lease->hwaddr_); EXPECT_EQ("0a:0b:0c:0d:0e", lease->hwaddr_->toText(false)); EXPECT_EQ(Lease::STATE_DECLINED, lease->state_); + ASSERT_TRUE(lease->getContext()); + EXPECT_EQ("{ \"foobar\": true }", lease->getContext()->str()); } } diff --git a/src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.cc index ed1208fe21..62f5feb9e8 100644 --- a/src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.cc +++ b/src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.cc @@ -22,6 +22,7 @@ using namespace std; using namespace isc::asiolink; +using namespace isc::data; namespace isc { namespace dhcp { @@ -156,6 +157,8 @@ GenericLeaseMgrTest::initializeLease4(std::string address) { lease->fqdn_rev_ = false; lease->fqdn_fwd_ = false; lease->hostname_ = "otherhost.example.com."; + lease->setContext(Element::fromJSON("{ \"foo\": true }")); + } else if (address == straddress4_[6]) { lease->hwaddr_.reset(new HWAddr(vector(6, 0x6e), HTYPE_ETHER)); // Same ClientId as straddress4_1 @@ -177,6 +180,7 @@ GenericLeaseMgrTest::initializeLease4(std::string address) { lease->fqdn_rev_ = true; lease->fqdn_fwd_ = true; lease->hostname_ = "myhost.example.com."; + lease->setContext(Element::fromJSON("{ \"bar\": false }")); } else { // Unknown address, return an empty pointer. @@ -288,6 +292,7 @@ GenericLeaseMgrTest::initializeLease6(std::string address) { lease->fqdn_fwd_ = false; lease->fqdn_rev_ = true; lease->hostname_ = "hostname.example.com."; + lease->setContext(Element::fromJSON("{ \"foo\": true }")); } else if (address == straddress6_[6]) { // Same DUID as straddress6_1 @@ -317,6 +322,7 @@ GenericLeaseMgrTest::initializeLease6(std::string address) { lease->fqdn_fwd_ = false; lease->fqdn_rev_ = true; lease->hostname_ = "hostname.example.com."; + lease->setContext(Element::fromJSON("{ \"bar\": false }")); } else { // Unknown address, return an empty pointer. @@ -533,6 +539,17 @@ GenericLeaseMgrTest::testGetLease4HWAddr2() { // Should be three leases, matching leases[1], [3] and [5]. ASSERT_EQ(3, returned.size()); + // Check the lease[5] (and only this one) has an user context. + size_t contexts = 0; + for (Lease4Collection::const_iterator i = returned.begin(); + i != returned.end(); ++i) { + if ((*i)->getContext()) { + ++contexts; + EXPECT_EQ("{ \"foo\": true }", (*i)->getContext()->str()); + } + } + EXPECT_EQ(1, contexts); + // Easiest way to check is to look at the addresses. vector addresses; for (Lease4Collection::const_iterator i = returned.begin(); @@ -708,6 +725,7 @@ void GenericLeaseMgrTest::testBasicLease4() { // Get the leases to be used for the test. vector leases = createLeases4(); + leases[2]->setContext(Element::fromJSON("{ \"foobar\": 1234 }")); // Start the tests. Add three leases to the database, read them back and // check they are what we think they are. @@ -785,6 +803,7 @@ void GenericLeaseMgrTest::testBasicLease6() { // Get the leases to be used for the test. vector leases = createLeases6(); + leases[2]->setContext(Element::fromJSON("{ \"foobar\": 1234 }")); // Start the tests. Add three leases to the database, read them back and // check they are what we think they are. @@ -1123,6 +1142,17 @@ GenericLeaseMgrTest::testGetLease4ClientId2() { // Should be four leases, matching leases[1], [4], [5] and [6]. ASSERT_EQ(4, returned.size()); + // Check the lease[5] (and only this one) has an user context. + size_t contexts = 0; + for (Lease4Collection::const_iterator i = returned.begin(); + i != returned.end(); ++i) { + if ((*i)->getContext()) { + ++contexts; + EXPECT_EQ("{ \"foo\": true }", (*i)->getContext()->str()); + } + } + EXPECT_EQ(1, contexts); + // Easiest way to check is to look at the addresses. vector addresses; for (Lease4Collection::const_iterator i = returned.begin(); @@ -1516,6 +1546,7 @@ GenericLeaseMgrTest::testUpdateLease4() { leases[1]->hostname_ = "modified.hostname."; leases[1]->fqdn_fwd_ = !leases[1]->fqdn_fwd_; leases[1]->fqdn_rev_ = !leases[1]->fqdn_rev_;; + leases[1]->setContext(Element::fromJSON("{ \"foobar\": 1234 }")); lmptr_->updateLease4(leases[1]); // ... and check what is returned is what is expected. @@ -1526,6 +1557,7 @@ GenericLeaseMgrTest::testUpdateLease4() { // Alter the lease again and check. ++leases[1]->subnet_id_; leases[1]->cltt_ += 6; + leases[1]->setContext(Element::fromJSON("{ \"foo\": \"bar\" }")); lmptr_->updateLease4(leases[1]); // Explicitly clear the returned pointer before getting new data to ensure @@ -1572,6 +1604,7 @@ GenericLeaseMgrTest::testUpdateLease6() { leases[1]->hostname_ = "modified.hostname.v6."; leases[1]->fqdn_fwd_ = !leases[1]->fqdn_fwd_; leases[1]->fqdn_rev_ = !leases[1]->fqdn_rev_;; + leases[1]->setContext(Element::fromJSON("{ \"foobar\": 1234 }")); lmptr_->updateLease6(leases[1]); lmptr_->commit(); @@ -1586,6 +1619,7 @@ GenericLeaseMgrTest::testUpdateLease6() { leases[1]->type_ = Lease::TYPE_TA; leases[1]->cltt_ += 6; leases[1]->prefixlen_ = 93; + leases[1]->setContext(Element::fromJSON("{ \"foo\": \"bar\" }")); lmptr_->updateLease6(leases[1]); l_returned.reset(); diff --git a/src/lib/dhcpsrv/tests/lease_file_loader_unittest.cc b/src/lib/dhcpsrv/tests/lease_file_loader_unittest.cc index 4ac5165df0..1670f81087 100644 --- a/src/lib/dhcpsrv/tests/lease_file_loader_unittest.cc +++ b/src/lib/dhcpsrv/tests/lease_file_loader_unittest.cc @@ -18,6 +18,7 @@ using namespace isc; using namespace isc::asiolink; +using namespace isc::data; using namespace isc::dhcp; using namespace isc::dhcp::test; @@ -171,9 +172,11 @@ LeaseFileLoaderTest::absolutePath(const std::string& filename) { TEST_F(LeaseFileLoaderTest, loadWrite4) { std::string test_str; std::string a_1 = "192.0.2.1,06:07:08:09:0a:bc,," - "200,200,8,1,1,host.example.com,1,\n"; + "200,200,8,1,1,host.example.com,1," + "{ \"foobar\": true }\n"; std::string a_2 = "192.0.2.1,06:07:08:09:0a:bc,," - "200,500,8,1,1,host.example.com,1,\n"; + "200,500,8,1,1,host.example.com,1," + "{ \"foobar\": true }\n"; std::string b_1 = "192.0.3.15,dd:de:ba:0d:1b:2e:3e:4f,0a:00:01:04," "100,100,7,0,0,,1,\n"; @@ -212,6 +215,10 @@ TEST_F(LeaseFileLoaderTest, loadWrite4) { ASSERT_TRUE(lease); EXPECT_EQ(300, lease->cltt_); + // The lease for 192.0.2.1 should have user context. + ASSERT_TRUE(lease->getContext()); + EXPECT_EQ("{ \"foobar\": true }", lease->getContext()->str()); + // The invalid entry should not be loaded. lease = getLease("192.0.2.3", storage); ASSERT_FALSE(lease); @@ -222,6 +229,7 @@ TEST_F(LeaseFileLoaderTest, loadWrite4) { lease = getLease("192.0.3.15", storage); ASSERT_TRUE(lease); EXPECT_EQ(35, lease->cltt_); + EXPECT_FALSE(lease->getContext()); test_str = v4_hdr_ + a_2 + b_2; writeLeases(*lf, storage, test_str); @@ -297,12 +305,14 @@ TEST_F(LeaseFileLoaderTest, loadWrite4LeaseRemove) { TEST_F(LeaseFileLoaderTest, loadWrite6) { std::string test_str; std::string a_1 = "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f," - "200,200,8,100,0,7,0,1,1,host.example.com,,1,\n"; + "200,200,8,100,0,7,0,1,1,host.example.com,,1," + "{ \"foobar\": true }\n"; std::string a_2 = "2001:db8:1::1,," - "200,200,8,100,0,7,0,1,1,host.example.com,,1,\n"; + "200,200,8,100,0,7,0,1,1,host.example.com,,1," + "{ \"foobar\": true }\n"; std::string a_3 = "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f," - "200,400,8,100,0,7,0,1,1,host.example.com,,1,\n"; - + "200,400,8,100,0,7,0,1,1,host.example.com,,1," + "{ \"foobar\": true }\n"; std::string b_1 = "2001:db8:2::10,01:01:01:01:0a:01:02:03:04:05," "300,300,6,150,0,8,0,0,0,,,1,\n"; std::string b_2 = "2001:db8:2::10,01:01:01:01:0a:01:02:03:04:05," @@ -312,7 +322,6 @@ TEST_F(LeaseFileLoaderTest, loadWrite6) { "100,200,8,0,2,16,64,0,0,,,1,\n"; - // Create a lease file with three valid leases: 2001:db8:1::1, // 3000:1:: and 2001:db8:2::10. test_str = v6_hdr_ + a_1 + a_2 + b_1 + c_1 + b_2 + a_3; @@ -341,16 +350,22 @@ TEST_F(LeaseFileLoaderTest, loadWrite6) { ASSERT_TRUE(lease); EXPECT_EQ(200, lease->cltt_); + // The 2001:db8:1::1 should have user context. + ASSERT_TRUE(lease->getContext()); + EXPECT_EQ("{ \"foobar\": true }", lease->getContext()->str()); + // The 3000:1:: lease should be present. lease = getLease("3000:1::", storage); ASSERT_TRUE(lease); EXPECT_EQ(100, lease->cltt_); + EXPECT_FALSE(lease->getContext()); // The 2001:db8:2::10 should be present and the cltt should be // calculated according to the last entry in the lease file. lease = getLease("2001:db8:2::10", storage); ASSERT_TRUE(lease); EXPECT_EQ(500, lease->cltt_); + EXPECT_FALSE(lease->getContext()); test_str = v6_hdr_ + a_3 + b_2 + c_1; writeLeases(*lf, storage, test_str); diff --git a/src/lib/dhcpsrv/tests/lease_unittest.cc b/src/lib/dhcpsrv/tests/lease_unittest.cc index a81719e503..8b3bac04f2 100644 --- a/src/lib/dhcpsrv/tests/lease_unittest.cc +++ b/src/lib/dhcpsrv/tests/lease_unittest.cc @@ -140,6 +140,7 @@ TEST_F(Lease4Test, constructor) { EXPECT_TRUE(lease.fqdn_fwd_); EXPECT_TRUE(lease.fqdn_rev_); EXPECT_EQ(Lease::STATE_DEFAULT, lease.state_); + EXPECT_FALSE(lease.getContext()); } } @@ -157,6 +158,9 @@ TEST_F(Lease4Test, copyConstructor) { // or the default state will be set for the copied lease. lease.state_ = Lease::STATE_DECLINED; + // Set an user context. + lease.setContext(Element::fromJSON("{ \"foobar\": 1234 }")); + // Use copy constructor to copy the lease. Lease4 copied_lease(lease); @@ -166,6 +170,11 @@ TEST_F(Lease4Test, copyConstructor) { // Client IDs are equal, but they should be in two distinct pointers. EXPECT_FALSE(lease.client_id_ == copied_lease.client_id_); + // User context are equal and point to the same object. + ASSERT_TRUE(copied_lease.getContext()); + EXPECT_TRUE(lease.getContext() == copied_lease.getContext()); + EXPECT_TRUE(*lease.getContext() == *copied_lease.getContext()); + // Hardware addresses are equal, but they should point to two objects, // each holding the same data. The content should be equal... EXPECT_TRUE(*lease.hwaddr_ == *copied_lease.hwaddr_); @@ -194,6 +203,9 @@ TEST_F(Lease4Test, operatorAssign) { // or the default state will be set for the copied lease. lease.state_ = Lease::STATE_DECLINED; + // Set an user context. + lease.setContext(Element::fromJSON("{ \"foobar\": 1234 }")); + // Create a default lease. Lease4 copied_lease; // Use assignment operator to assign new lease. @@ -205,6 +217,11 @@ TEST_F(Lease4Test, operatorAssign) { // Client IDs are equal, but they should be in two distinct pointers. EXPECT_FALSE(lease.client_id_ == copied_lease.client_id_); + // User context are equal and point to the same object. + ASSERT_TRUE(copied_lease.getContext()); + EXPECT_TRUE(lease.getContext() == copied_lease.getContext()); + EXPECT_TRUE(*lease.getContext() == *copied_lease.getContext()); + // Hardware addresses are equal, but they should point to two objects, // each holding the same data. The content should be equal... EXPECT_TRUE(*lease.hwaddr_ == *copied_lease.hwaddr_); @@ -294,6 +311,7 @@ TEST_F(Lease4Test, operatorEquals) { // Check when the leases are equal. Lease4 lease1(ADDRESS, hwaddr_, clientid_, VALID_LIFETIME, current_time, 0, 0, SUBNET_ID); + lease1.setContext(Element::fromJSON("{ \"foobar\": 1234 }")); // We need to make an explicit copy. Otherwise the second lease will just // store a pointer and we'll have two leases pointing to a single HWAddr @@ -303,6 +321,7 @@ TEST_F(Lease4Test, operatorEquals) { Lease4 lease2(ADDRESS, hwcopy, clientid_copy, VALID_LIFETIME, current_time, 0, 0, SUBNET_ID); + lease2.setContext(Element::fromJSON("{ \"foobar\": 1234 }")); EXPECT_TRUE(lease1 == lease2); EXPECT_FALSE(lease1 != lease2); @@ -394,6 +413,20 @@ TEST_F(Lease4Test, operatorEquals) { lease2.state_ += 1; EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the EXPECT_FALSE(lease1 != lease2); // ... leases equal + + lease1.setContext(Element::fromJSON("{ \"foobar\": 5678 }")); + EXPECT_FALSE(lease1 == lease2); + EXPECT_TRUE(lease1 != lease2); + lease1.setContext(Element::fromJSON("{ \"foobar\": 1234 }")); + EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the + EXPECT_FALSE(lease1 != lease2); // ... leases equal + + lease1.setContext(ConstElementPtr()); + EXPECT_FALSE(lease1 == lease2); + EXPECT_TRUE(lease1 != lease2); + lease2.setContext(ConstElementPtr()); + EXPECT_TRUE(lease1 == lease2); // Check that no user context has mase the + EXPECT_FALSE(lease1 != lease2); // ... leases equal } // Verify that the client id can be returned as a vector object and if client @@ -438,6 +471,7 @@ TEST_F(Lease4Test, toText) { const time_t current_time = 12345678; Lease4 lease(IOAddress("192.0.2.3"), hwaddr_, clientid_, 3600, 123, 456, current_time, 789); + lease.setContext(Element::fromJSON("{ \"foobar\": 1234 }")); std::stringstream expected; expected << "Address: 192.0.2.3\n" @@ -448,13 +482,16 @@ TEST_F(Lease4Test, toText) { << "Hardware addr: " << hwaddr_->toText(false) << "\n" << "Client id: " << clientid_->toText() << "\n" << "Subnet ID: 789\n" - << "State: default\n"; + << "State: default\n" + << "User context: { \"foobar\": 1234 }\n"; EXPECT_EQ(expected.str(), lease.toText()); - // Now let's try with a lease without hardware address and client identifier. + // Now let's try with a lease without hardware address, client identifier + // and user context. lease.hwaddr_.reset(); lease.client_id_.reset(); + lease.setContext(ConstElementPtr()); expected.str(""); expected << "Address: 192.0.2.3\n" << "Valid life: 3600\n" @@ -474,6 +511,7 @@ TEST_F(Lease4Test, toElement) { const time_t current_time = 12345678; Lease4 lease(IOAddress("192.0.2.3"), hwaddr_, clientid_, 3600, 123, 456, current_time, 789, true, true, "urania.example.org"); + lease.setContext(Element::fromJSON("{ \"foobar\": 1234 }")); std::string expected = "{" "\"client-id\": \"17:34:e2:ff:09:92:54\"," @@ -485,16 +523,36 @@ TEST_F(Lease4Test, toElement) { "\"ip-address\": \"192.0.2.3\"," "\"state\": 0," "\"subnet-id\": 789," + "\"user-context\": { \"foobar\": 1234 }," "\"valid-lft\": 3600 " "}"; runToElementTest(expected, lease); - // Now let's try with a lease without client-id. + // Now let's try with a lease without client-id and user context. lease.client_id_.reset(); + lease.setContext(ConstElementPtr()); + + expected = "{" + "\"cltt\": 12345678," + "\"fqdn-fwd\": true," + "\"fqdn-rev\": true," + "\"hostname\": \"urania.example.org\"," + "\"hw-address\": \"08:00:2b:02:3f:4e\"," + "\"ip-address\": \"192.0.2.3\"," + "\"state\": 0," + "\"subnet-id\": 789," + "\"valid-lft\": 3600 " + "}"; + + runToElementTest(expected, lease); + + // And to finish try with a comment. + lease.setContext(Element::fromJSON("{ \"comment\": \"a comment\" }")); expected = "{" "\"cltt\": 12345678," + "\"comment\": \"a comment\"," "\"fqdn-fwd\": true," "\"fqdn-rev\": true," "\"hostname\": \"urania.example.org\"," @@ -520,6 +578,7 @@ TEST_F(Lease4Test, fromElement) { "\"ip-address\": \"192.0.2.3\"," "\"state\": 0," "\"subnet-id\": 789," + "\"user-context\": { \"foo\": \"bar\" }," "\"valid-lft\": 3600 " "}"; @@ -540,6 +599,8 @@ TEST_F(Lease4Test, fromElement) { EXPECT_TRUE(lease->fqdn_rev_); EXPECT_EQ("urania.example.org", lease->hostname_); EXPECT_EQ(Lease::STATE_DEFAULT, lease->state_); + ASSERT_TRUE(lease->getContext()); + EXPECT_EQ("{ \"foo\": \"bar\" }", lease->getContext()->str()); } // Test that specifying invalid values for a lease or not specifying @@ -578,6 +639,10 @@ TEST_F(Lease4Test, fromElementInvalidValues) { testInvalidElement(json, "subnet-id", -5, false); testInvalidElement(json, "valid-lft", std::string("xyz")); testInvalidElement(json, "valid-lft", -3, false); + testInvalidElement(json, "user-context", "[ ]", false); + testInvalidElement(json, "user-context", 1234, false); + testInvalidElement(json, "user-context", false, false); + testInvalidElement(json, "user-context", "foo", false); } // Verify that decline() method properly clears up specific fields. @@ -607,6 +672,7 @@ TEST_F(Lease4Test, decline) { EXPECT_FALSE(lease.fqdn_rev_); EXPECT_EQ(Lease::STATE_DECLINED, lease.state_); EXPECT_EQ(123, lease.valid_lft_); + EXPECT_FALSE(lease.getContext()); } // Verify that the lease states are correctly returned in the textual format. @@ -668,7 +734,7 @@ TEST(Lease6Test, Lease6ConstructorDefault) { EXPECT_FALSE(lease->fqdn_fwd_); EXPECT_FALSE(lease->fqdn_rev_); EXPECT_TRUE(lease->hostname_.empty()); - + EXPECT_FALSE(lease->getContext()); } // Lease6 must be instantiated with a DUID, not with NULL pointer @@ -745,6 +811,9 @@ TEST(Lease6Test, operatorEquals) { Lease6 lease2(Lease::TYPE_NA, addr, duid, iaid, 100, 200, 50, 80, subnet_id); + lease1.setContext(Element::fromJSON("{ \"foobar\": 1234 }")); + lease2.setContext(Element::fromJSON("{ \"foobar\": 1234 }")); + // cltt_ constructs with time(NULL), make sure they are always equal lease1.cltt_ = lease2.cltt_; @@ -859,6 +928,20 @@ TEST(Lease6Test, operatorEquals) { lease2.state_ += 1; EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the EXPECT_FALSE(lease1 != lease2); // ... leases equal + + lease1.setContext(Element::fromJSON("{ \"foobar\": 5678 }")); + EXPECT_FALSE(lease1 == lease2); + EXPECT_TRUE(lease1 != lease2); + lease1.setContext(Element::fromJSON("{ \"foobar\": 1234 }")); + EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the + EXPECT_FALSE(lease1 != lease2); // ... leases equal + + lease1.setContext(ConstElementPtr()); + EXPECT_FALSE(lease1 == lease2); + EXPECT_TRUE(lease1 != lease2); + lease2.setContext(ConstElementPtr()); + EXPECT_TRUE(lease1 == lease2); // Check that no user context has mase the + EXPECT_FALSE(lease1 != lease2); // ... leases equal } // Checks if lease expiration is calculated properly @@ -941,6 +1024,7 @@ TEST(Lease6Test, decline) { EXPECT_FALSE(lease.fqdn_rev_); EXPECT_EQ(Lease::STATE_DECLINED, lease.state_); EXPECT_EQ(123, lease.valid_lft_); + EXPECT_FALSE(lease.getContext()); } // Verify the behavior of the function which checks FQDN data for equality. @@ -972,6 +1056,7 @@ TEST(Lease6Test, toText) { 400, 800, 100, 200, 5678, hwaddr, 128); lease.cltt_ = 12345678; lease.state_ = Lease::STATE_DECLINED; + lease.setContext(Element::fromJSON("{ \"foobar\": 1234 }")); std::stringstream expected; expected << "Type: IA_NA(" << static_cast(Lease::TYPE_NA) << ")\n" @@ -984,12 +1069,14 @@ TEST(Lease6Test, toText) { << "DUID: 00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f\n" << "Hardware addr: " << hwaddr->toText(false) << "\n" << "Subnet ID: 5678\n" - << "State: declined\n"; + << "State: declined\n" + << "User context: { \"foobar\": 1234 }\n"; EXPECT_EQ(expected.str(), lease.toText()); - // Now let's try with a lease without hardware address. + // Now let's try with a lease without hardware address and user context. lease.hwaddr_.reset(); + lease.setContext(ConstElementPtr()); expected.str(""); expected << "Type: IA_NA(" << static_cast(Lease::TYPE_NA) << ")\n" << "Address: 2001:db8::1\n" @@ -1019,6 +1106,7 @@ TEST(Lease6Test, toElementAddress) { lease.cltt_ = 12345678; lease.state_ = Lease::STATE_DECLINED; lease.hostname_ = "urania.example.org"; + lease.setContext(Element::fromJSON("{ \"foobar\": 1234 }")); std::string expected = "{" "\"cltt\": 12345678," @@ -1033,16 +1121,39 @@ TEST(Lease6Test, toElementAddress) { "\"state\": 1," "\"subnet-id\": 5678," "\"type\": \"IA_NA\"," + "\"user-context\": { \"foobar\": 1234 }," "\"valid-lft\": 800" "}"; runToElementTest(expected, lease); - // Now let's try with a lease without hardware address. + // Now let's try with a lease without hardware address and user context. lease.hwaddr_.reset(); + lease.setContext(ConstElementPtr()); + + expected = "{" + "\"cltt\": 12345678," + "\"duid\": \"00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f\"," + "\"fqdn-fwd\": false," + "\"fqdn-rev\": false," + "\"hostname\": \"urania.example.org\"," + "\"iaid\": 123456," + "\"ip-address\": \"2001:db8::1\"," + "\"preferred-lft\": 400," + "\"state\": 1," + "\"subnet-id\": 5678," + "\"type\": \"IA_NA\"," + "\"valid-lft\": 800" + "}"; + + runToElementTest(expected, lease); + + // And to finish try with a comment. + lease.setContext(Element::fromJSON("{ \"comment\": \"a comment\" }")); expected = "{" "\"cltt\": 12345678," + "\"comment\": \"a comment\"," "\"duid\": \"00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f\"," "\"fqdn-fwd\": false," "\"fqdn-rev\": false," @@ -1073,6 +1184,7 @@ TEST(Lease6Test, toElementPrefix) { lease.cltt_ = 12345678; lease.state_ = Lease::STATE_DEFAULT; lease.hostname_ = "urania.example.org"; + lease.setContext(Element::fromJSON("{ \"foobar\": 1234 }")); ElementPtr l = lease.toElement(); @@ -1120,10 +1232,24 @@ TEST(Lease6Test, toElementPrefix) { ASSERT_TRUE(l->contains("hostname")); EXPECT_EQ("urania.example.org", l->get("hostname")->stringValue()); - // Now let's try with a lease without hardware address. + ASSERT_TRUE(l->contains("user-context")); + EXPECT_EQ("{ \"foobar\": 1234 }", l->get("user-context")->str()); + + // Now let's try with a lease without hardware address or user context. lease.hwaddr_.reset(); + lease.setContext(ConstElementPtr()); l = lease.toElement(); EXPECT_FALSE(l->contains("hw-address")); + EXPECT_FALSE(l->contains("user-context")); + EXPECT_FALSE(l->contains("comment")); + + // And to finish try with a comment. + lease.setContext(Element::fromJSON("{ \"comment\": \"a comment\" }")); + l = lease.toElement(); + EXPECT_FALSE(l->contains("hw-address")); + EXPECT_FALSE(l->contains("user-context")); + ASSERT_TRUE(l->contains("comment")); + EXPECT_EQ("a comment", l->get("comment")->stringValue()); } // Verify that the IA_NA can be created from JSON. @@ -1141,6 +1267,7 @@ TEST(Lease6Test, fromElementNA) { "\"state\": 1," "\"subnet-id\": 5678," "\"type\": \"IA_NA\"," + "\"user-context\": { \"foobar\": 1234 }," "\"valid-lft\": 800" "}"; @@ -1159,6 +1286,8 @@ TEST(Lease6Test, fromElementNA) { EXPECT_FALSE(lease->fqdn_rev_); EXPECT_EQ("urania.example.org", lease->hostname_); EXPECT_EQ(Lease::STATE_DECLINED, lease->state_); + ASSERT_TRUE(lease->getContext()); + EXPECT_EQ("{ \"foobar\": 1234 }", lease->getContext()->str()); // IPv6 specific properties. EXPECT_EQ(Lease::TYPE_NA, lease->type_); @@ -1169,7 +1298,7 @@ TEST(Lease6Test, fromElementNA) { EXPECT_EQ(400, lease->preferred_lft_); } -// Verify that the IA_NA can be created from JSON. +// Verify that the IA_PD can be created from JSON. TEST(Lease6Test, fromElementPD) { std::string json = "{" "\"cltt\": 12345678," @@ -1203,6 +1332,7 @@ TEST(Lease6Test, fromElementPD) { EXPECT_FALSE(lease->fqdn_rev_); EXPECT_EQ("urania.example.org", lease->hostname_); EXPECT_EQ(Lease::STATE_DEFAULT , lease->state_); + EXPECT_FALSE(lease->getContext()); // IPv6 specific properties. EXPECT_EQ(Lease::TYPE_PD, lease->type_); @@ -1262,6 +1392,10 @@ TEST(Lease6Test, fromElementInvalidValues) { testInvalidElement(json, "type", -3, false); testInvalidElement(json, "valid-lft", std::string("xyz")); testInvalidElement(json, "valid-lft", -3, false); + testInvalidElement(json, "user-context", "[ ]", false); + testInvalidElement(json, "user-context", 1234, false); + testInvalidElement(json, "user-context", false, false); + testInvalidElement(json, "user-context", "foo", false); } // Verify that the lease states are correctly returned in the textual format. diff --git a/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc index 3b99cedbe4..8d4a986ad6 100644 --- a/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc +++ b/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc @@ -504,14 +504,14 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCleanup4) { // one lease, but two entries. One of the entries should be removed // as a result of lease file cleanup. std::string current_file_contents = new_file_contents + - "192.0.2.2,02:02:02:02:02:02,,200,200,8,1,1,,1,\n" + "192.0.2.2,02:02:02:02:02:02,,200,200,8,1,1,,1,{ \"foo\": true }\n" "192.0.2.2,02:02:02:02:02:02,,200,800,8,1,1,,1,\n"; LeaseFileIO current_file(getLeaseFilePath("leasefile4_0.csv")); current_file.writeFile(current_file_contents); std::string previous_file_contents = new_file_contents + "192.0.2.3,03:03:03:03:03:03,,200,200,8,1,1,,1,\n" - "192.0.2.3,03:03:03:03:03:03,,200,800,8,1,1,,1,\n"; + "192.0.2.3,03:03:03:03:03:03,,200,800,8,1,1,,1,{ \"bar\": true }\n"; LeaseFileIO previous_file(getLeaseFilePath("leasefile4_0.csv.2")); previous_file.writeFile(previous_file_contents); @@ -556,7 +556,7 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCleanup4) { // entry each. std::string result_file_contents = new_file_contents + "192.0.2.2,02:02:02:02:02:02,,200,800,8,1,1,,1,\n" - "192.0.2.3,03:03:03:03:03:03,,200,800,8,1,1,,1,\n"; + "192.0.2.3,03:03:03:03:03:03,,200,800,8,1,1,,1,{ \"bar\": true }\n"; // The LFC should have created a file with the two leases and moved it // to leasefile4_0.csv.2 @@ -584,13 +584,13 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCleanup6) { "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,200,200," "8,100,0,7,0,1,1,,,1,\n" "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,200,800," - "8,100,0,7,0,1,1,,,1,\n"; + "8,100,0,7,0,1,1,,,1,{ \"foo\": true }\n"; LeaseFileIO current_file(getLeaseFilePath("leasefile6_0.csv")); current_file.writeFile(current_file_contents); std::string previous_file_contents = new_file_contents + "2001:db8:1::2,01:01:01:01:01:01:01:01:01:01:01:01:01,200,200," - "8,100,0,7,0,1,1,,,1,\n" + "8,100,0,7,0,1,1,,,1,{ \"bar\": true }\n" "2001:db8:1::2,01:01:01:01:01:01:01:01:01:01:01:01:01,200,800," "8,100,0,7,0,1,1,,,1,\n"; LeaseFileIO previous_file(getLeaseFilePath("leasefile6_0.csv.2")); @@ -639,7 +639,7 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCleanup6) { // entry each. std::string result_file_contents = new_file_contents + "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,200,800," - "8,100,0,7,0,1,1,,,1,\n" + "8,100,0,7,0,1,1,,,1,{ \"foo\": true }\n" "2001:db8:1::2,01:01:01:01:01:01:01:01:01:01:01:01:01,200,800," "8,100,0,7,0,1,1,,,1,\n"; @@ -771,7 +771,7 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCopy) { "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,200,200," "8,100,0,7,0,1,1,,,1,\n" "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,200,800," - "8,100,0,7,0,1,1,,,1,\n"; + "8,100,0,7,0,1,1,,,1,{ \"foo\": true }\n"; LeaseFileIO current_file(getLeaseFilePath("leasefile6_0.csv")); current_file.writeFile(current_file_contents); @@ -781,7 +781,7 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCopy) { // the same. std::string input_file_contents = new_file_contents + "2001:db8:1::2,01:01:01:01:01:01:01:01:01:01:01:01:01,200,800," - "8,100,0,7,0,1,1,,,1,\n"; + "8,100,0,7,0,1,1,,,1,{ \"foo\": true }\n"; LeaseFileIO input_file(getLeaseFilePath("leasefile6_0.csv.1")); input_file.writeFile(input_file_contents); diff --git a/src/lib/dhcpsrv/tests/test_utils.cc b/src/lib/dhcpsrv/tests/test_utils.cc index 0d7463280d..3634e4ceb6 100644 --- a/src/lib/dhcpsrv/tests/test_utils.cc +++ b/src/lib/dhcpsrv/tests/test_utils.cc @@ -54,6 +54,14 @@ detailCompareLease(const Lease4Ptr& first, const Lease4Ptr& second) { EXPECT_EQ(first->fqdn_fwd_, second->fqdn_fwd_); EXPECT_EQ(first->fqdn_rev_, second->fqdn_rev_); EXPECT_EQ(first->hostname_, second->hostname_); + if (first->getContext()) { + EXPECT_TRUE(second->getContext()); + if (second->getContext()) { + EXPECT_EQ(first->getContext()->str(), second->getContext()->str()); + } + } else { + EXPECT_FALSE(second->getContext()); + } } void @@ -77,6 +85,14 @@ detailCompareLease(const Lease6Ptr& first, const Lease6Ptr& second) { EXPECT_EQ(first->fqdn_fwd_, second->fqdn_fwd_); EXPECT_EQ(first->fqdn_rev_, second->fqdn_rev_); EXPECT_EQ(first->hostname_, second->hostname_); + if (first->getContext()) { + EXPECT_TRUE(second->getContext()); + if (second->getContext()) { + EXPECT_EQ(first->getContext()->str(), second->getContext()->str()); + } + } else { + EXPECT_FALSE(second->getContext()); + } } int findLastSocketFd() { diff --git a/src/share/database/scripts/cql/upgrade_2.0_to_3.0.sh.in b/src/share/database/scripts/cql/upgrade_2.0_to_3.0.sh.in index b52f165580..96956adf6f 100644 --- a/src/share/database/scripts/cql/upgrade_2.0_to_3.0.sh.in +++ b/src/share/database/scripts/cql/upgrade_2.0_to_3.0.sh.in @@ -24,7 +24,7 @@ ALTER TABLE lease4 ADD user_context text; ALTER TABLE lease6 ADD user_context text; -- ----------------------------------------------------- --- Table `logs` +-- Table \`logs\` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS logs ( timeuuid timeuuid, -- creation timeuuid, use dateOf() to get timestamp diff --git a/src/share/database/scripts/mysql/dhcpdb_create.mysql b/src/share/database/scripts/mysql/dhcpdb_create.mysql index f71f6160c8..022aadb48f 100644 --- a/src/share/database/scripts/mysql/dhcpdb_create.mysql +++ b/src/share/database/scripts/mysql/dhcpdb_create.mysql @@ -681,6 +681,77 @@ SET version = '6', minor = '0'; ALTER TABLE lease4 ADD COLUMN user_context TEXT NULL; ALTER TABLE lease6 ADD COLUMN user_context TEXT NULL; +DROP PROCEDURE IF EXISTS lease4DumpHeader; +DELIMITER $$ +CREATE PROCEDURE lease4DumpHeader() +BEGIN +SELECT 'address,hwaddr,client_id,valid_lifetime,expire,subnet_id,fqdn_fwd,fqdn_rev,hostname,state,user_context'; +END $$ +DELIMITER ; + +# FUNCTION that returns a result set containing the data for lease4 dumps +DROP PROCEDURE IF EXISTS lease4DumpData; +DELIMITER $$ +CREATE PROCEDURE lease4DumpData() +BEGIN +SELECT + INET_NTOA(l.address), + IFNULL(HEX(l.hwaddr), ''), + IFNULL(HEX(l.client_id), ''), + l.valid_lifetime, + l.expire, + l.subnet_id, + l.fqdn_fwd, + l.fqdn_rev, + l.hostname, + s.name, + IFNULL(l.user_context, '') +FROM + lease4 l + LEFT OUTER JOIN lease_state s on (l.state = s.state) +ORDER BY l.address; +END $$ +DELIMITER ; + +DROP PROCEDURE IF EXISTS lease6DumpHeader; +DELIMITER $$ +CREATE PROCEDURE lease6DumpHeader() +BEGIN +SELECT 'address,duid,valid_lifetime,expire,subnet_id,pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,hwtype,hwaddr_source,state,user_context'; +END $$ +DELIMITER ; + +# FUNCTION that returns a result set containing the data for lease6 dumps +DROP PROCEDURE IF EXISTS lease6DumpData; +DELIMITER $$ +CREATE PROCEDURE lease6DumpData() +BEGIN +SELECT + l.address, + IFNULL(HEX(l.duid), ''), + l.valid_lifetime, + l.expire, + l.subnet_id, + l.pref_lifetime, + IFNULL(t.name, ''), + l.iaid, + l.prefix_len, + l.fqdn_fwd, + l.fqdn_rev, + l.hostname, + IFNULL(HEX(l.hwaddr), ''), + IFNULL(l.hwtype, ''), + IFNULL(h.name, ''), + IFNULL(s.name, ''), + IFNULL(l.user_context, '') +FROM lease6 l + left outer join lease6_types t on (l.lease_type = t.lease_type) + left outer join lease_state s on (l.state = s.state) + left outer join lease_hwaddr_source h on (l.hwaddr_source = h.hwaddr_source) +ORDER BY l.address; +END $$ +DELIMITER ; + # Create logs table CREATE TABLE logs ( timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP, # creation timestamp diff --git a/src/share/database/scripts/mysql/upgrade_6.0_to_6.1.sh.in b/src/share/database/scripts/mysql/upgrade_6.0_to_6.1.sh.in index 8f1c0f94a5..fea2d8cb27 100644 --- a/src/share/database/scripts/mysql/upgrade_6.0_to_6.1.sh.in +++ b/src/share/database/scripts/mysql/upgrade_6.0_to_6.1.sh.in @@ -21,6 +21,77 @@ mysql "$@" <