mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-29 13:07:50 +00:00
[5533a] Rebased
This commit is contained in:
commit
fe232dabca
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -0,0 +1,3 @@
|
||||
[submodule "premium"]
|
||||
path = premium
|
||||
url = ssh://fdupont@repo.isc.org/proj/git/prod/kea-premium.git
|
@ -54,13 +54,17 @@
|
||||
// reservations list, within the subnet (configuration file). If there are
|
||||
// no reservations there, the server will try to retrieve reservations
|
||||
// from this database.
|
||||
"hosts-database": {
|
||||
"type": "postgresql",
|
||||
"name": "kea",
|
||||
"user": "kea",
|
||||
"password": "kea",
|
||||
"host": "localhost"
|
||||
},
|
||||
// The database specification can go into one hosts-database entry for
|
||||
// backward compatibility or be listed in hosts-databases list.
|
||||
"hosts-databases": [
|
||||
{
|
||||
"type": "postgresql",
|
||||
"name": "kea",
|
||||
"user": "kea",
|
||||
"password": "kea",
|
||||
"host": "localhost"
|
||||
}
|
||||
],
|
||||
|
||||
// Define a subnet with a single pool of dynamic addresses. Addresses from
|
||||
// this pool will be assigned to clients which don't have reservations in the
|
||||
|
@ -41,13 +41,17 @@
|
||||
// reservations list, within the subnet (configuration file). If there are
|
||||
// no reservations there, the server will try to retrieve reservations
|
||||
// from this database.
|
||||
"hosts-database": {
|
||||
"type": "postgresql",
|
||||
"name": "kea",
|
||||
"user": "kea",
|
||||
"password": "kea",
|
||||
"host": "localhost"
|
||||
},
|
||||
// The database specification can go into one hosts-database entry for
|
||||
// backward compatibility or be listed in hosts-databases list.
|
||||
"hosts-databases": [
|
||||
{
|
||||
"type": "postgresql",
|
||||
"name": "kea",
|
||||
"user": "kea",
|
||||
"password": "kea",
|
||||
"host": "localhost"
|
||||
}
|
||||
],
|
||||
|
||||
// Define a subnet with a pool of dynamic addresses and a pool of dynamic
|
||||
// prefixes. Addresses and prefixes from those pools will be assigned to
|
||||
|
@ -529,7 +529,13 @@ If a timeout is given though, it should be an integer greater than zero.
|
||||
from the configuration file are checked first and external storage is checked
|
||||
later, if necessary.</para>
|
||||
|
||||
<section xml:id="hosts-database-configuration4">
|
||||
<para>Version 1.4 extends the host storage to multiple storages. Operations
|
||||
are performed on host storages in the configuration order with a special
|
||||
case for addition: read-only storages must be configured after a
|
||||
required read-write storage, or host reservation addition will
|
||||
always fail.</para>
|
||||
|
||||
<section xml:id="hosts-databases-configuration4">
|
||||
<title>DHCPv4 Hosts Database Configuration</title>
|
||||
|
||||
<para>Hosts database configuration is controlled through the Dhcp4/hosts-database
|
||||
@ -572,6 +578,16 @@ If a timeout is given though, it should be an integer greater than zero.
|
||||
</screen>
|
||||
If there is no password to the account, set the password to the empty string
|
||||
"". (This is also the default.)</para>
|
||||
|
||||
<para>The multiple storage extension uses a similar syntax: a configuration
|
||||
is placed into a "hosts-databases" list instead of into a "hosts-database"
|
||||
entry as in:
|
||||
<screen>
|
||||
"Dhcp4": { "hosts-databases": [ { <userinput>"type": "mysql"</userinput>, ... }, ... ], ... }
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="read-only-database-configuration4">
|
||||
|
@ -525,7 +525,13 @@ If a timeout is given though, it should be an integer greater than zero.
|
||||
from the configuration file are checked first and external storage is checked
|
||||
later, if necessary.</para>
|
||||
|
||||
<section xml:id="hosts-database-configuration6">
|
||||
<para>Version 1.4 extends the host storage to multiple storages. Operations
|
||||
are performed on host storages in the configuration order with a special
|
||||
case for addition: read-only storages must be configured after a
|
||||
required read-write storage, or host reservation addition will
|
||||
always fail.</para>
|
||||
|
||||
<section xml:id="hosts-databases-configuration6">
|
||||
<title>DHCPv6 Hosts Database Configuration</title>
|
||||
|
||||
<para>Hosts database configuration is controlled through the Dhcp6/hosts-database
|
||||
@ -565,6 +571,16 @@ If a timeout is given though, it should be an integer greater than zero.
|
||||
</screen>
|
||||
If there is no password to the account, set the password to the empty string
|
||||
"". (This is also the default.)</para>
|
||||
|
||||
<para>The multiple storage extension uses a similar syntax: a configuration
|
||||
is placed into a "hosts-databases" list instead of into a "hosts-database"
|
||||
entry as in:
|
||||
<screen>
|
||||
"Dhcp6": { "hosts-databases": [ { <userinput>"type": "mysql"</userinput>, ... }, ... ], ... }
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="read-only-database-configuration6">
|
||||
|
@ -1083,9 +1083,9 @@ $
|
||||
criteria). To use commands that change the reservation information
|
||||
(currently these are reservation-add and reservation-del, but this
|
||||
rule applies to other commands that may be implemented in the future),
|
||||
hosts database must be specified (see hosts-database description in
|
||||
<xref linkend="hosts-database-configuration4"/> and <xref linkend="hosts-database-configuration6"/>) and it must not operate in
|
||||
read-only mode. If the hosts-database is not specified or is running
|
||||
hosts database must be specified (see hosts-databases description in
|
||||
<xref linkend="hosts-databases-configuration4"/> and <xref linkend="hosts-databases-configuration6"/>) and it must not operate in
|
||||
read-only mode. If the hosts-databases are not specified or are running
|
||||
in read-only mode, the host_cmds library will load, but any attempts
|
||||
to use reservation-add or reservation-del will fail.
|
||||
</para>
|
||||
@ -1204,8 +1204,8 @@ Here is an example of complex IPv6 reservation:
|
||||
|
||||
<para>
|
||||
As <command>reservation-add</command> is expected to store the host,
|
||||
hosts-database parameter must be specified in your configuration and
|
||||
the database must not run in read-only mode. In the future versions
|
||||
hosts-databases parameter must be specified in your configuration and
|
||||
databases must not run in read-only mode. In the future versions
|
||||
it will be possible to modify the reservations read from a
|
||||
configuration file. Please contact ISC if you are interested in this
|
||||
functionality.
|
||||
|
1
premium
Submodule
1
premium
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 7eae81e92f9ea28349f0c933a5123c20483bc078
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
/* Copyright (C) 2016-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
|
||||
@ -294,6 +294,15 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
|
||||
}
|
||||
}
|
||||
|
||||
\"hosts-databases\" {
|
||||
switch(driver.ctx_) {
|
||||
case isc::dhcp::Parser4Context::DHCP4:
|
||||
return isc::dhcp::Dhcp4Parser::make_HOSTS_DATABASES(driver.loc_);
|
||||
default:
|
||||
return isc::dhcp::Dhcp4Parser::make_STRING("hosts-databases", driver.loc_);
|
||||
}
|
||||
}
|
||||
|
||||
\"readonly\" {
|
||||
switch(driver.ctx_) {
|
||||
case isc::dhcp::Parser4Context::HOSTS_DATABASE:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -372,131 +372,132 @@ namespace isc { namespace dhcp {
|
||||
TOKEN_BOOT_FILE_NAME = 279,
|
||||
TOKEN_LEASE_DATABASE = 280,
|
||||
TOKEN_HOSTS_DATABASE = 281,
|
||||
TOKEN_TYPE = 282,
|
||||
TOKEN_MEMFILE = 283,
|
||||
TOKEN_MYSQL = 284,
|
||||
TOKEN_POSTGRESQL = 285,
|
||||
TOKEN_CQL = 286,
|
||||
TOKEN_USER = 287,
|
||||
TOKEN_PASSWORD = 288,
|
||||
TOKEN_HOST = 289,
|
||||
TOKEN_PORT = 290,
|
||||
TOKEN_PERSIST = 291,
|
||||
TOKEN_LFC_INTERVAL = 292,
|
||||
TOKEN_READONLY = 293,
|
||||
TOKEN_CONNECT_TIMEOUT = 294,
|
||||
TOKEN_CONTACT_POINTS = 295,
|
||||
TOKEN_KEYSPACE = 296,
|
||||
TOKEN_VALID_LIFETIME = 297,
|
||||
TOKEN_RENEW_TIMER = 298,
|
||||
TOKEN_REBIND_TIMER = 299,
|
||||
TOKEN_DECLINE_PROBATION_PERIOD = 300,
|
||||
TOKEN_SUBNET4 = 301,
|
||||
TOKEN_SUBNET_4O6_INTERFACE = 302,
|
||||
TOKEN_SUBNET_4O6_INTERFACE_ID = 303,
|
||||
TOKEN_SUBNET_4O6_SUBNET = 304,
|
||||
TOKEN_OPTION_DEF = 305,
|
||||
TOKEN_OPTION_DATA = 306,
|
||||
TOKEN_NAME = 307,
|
||||
TOKEN_DATA = 308,
|
||||
TOKEN_CODE = 309,
|
||||
TOKEN_SPACE = 310,
|
||||
TOKEN_CSV_FORMAT = 311,
|
||||
TOKEN_ALWAYS_SEND = 312,
|
||||
TOKEN_RECORD_TYPES = 313,
|
||||
TOKEN_ENCAPSULATE = 314,
|
||||
TOKEN_ARRAY = 315,
|
||||
TOKEN_SHARED_NETWORKS = 316,
|
||||
TOKEN_POOLS = 317,
|
||||
TOKEN_POOL = 318,
|
||||
TOKEN_USER_CONTEXT = 319,
|
||||
TOKEN_COMMENT = 320,
|
||||
TOKEN_SUBNET = 321,
|
||||
TOKEN_INTERFACE = 322,
|
||||
TOKEN_INTERFACE_ID = 323,
|
||||
TOKEN_ID = 324,
|
||||
TOKEN_RAPID_COMMIT = 325,
|
||||
TOKEN_RESERVATION_MODE = 326,
|
||||
TOKEN_DISABLED = 327,
|
||||
TOKEN_OUT_OF_POOL = 328,
|
||||
TOKEN_ALL = 329,
|
||||
TOKEN_HOST_RESERVATION_IDENTIFIERS = 330,
|
||||
TOKEN_CLIENT_CLASSES = 331,
|
||||
TOKEN_TEST = 332,
|
||||
TOKEN_CLIENT_CLASS = 333,
|
||||
TOKEN_RESERVATIONS = 334,
|
||||
TOKEN_DUID = 335,
|
||||
TOKEN_HW_ADDRESS = 336,
|
||||
TOKEN_CIRCUIT_ID = 337,
|
||||
TOKEN_CLIENT_ID = 338,
|
||||
TOKEN_HOSTNAME = 339,
|
||||
TOKEN_FLEX_ID = 340,
|
||||
TOKEN_RELAY = 341,
|
||||
TOKEN_IP_ADDRESS = 342,
|
||||
TOKEN_HOOKS_LIBRARIES = 343,
|
||||
TOKEN_LIBRARY = 344,
|
||||
TOKEN_PARAMETERS = 345,
|
||||
TOKEN_EXPIRED_LEASES_PROCESSING = 346,
|
||||
TOKEN_RECLAIM_TIMER_WAIT_TIME = 347,
|
||||
TOKEN_FLUSH_RECLAIMED_TIMER_WAIT_TIME = 348,
|
||||
TOKEN_HOLD_RECLAIMED_TIME = 349,
|
||||
TOKEN_MAX_RECLAIM_LEASES = 350,
|
||||
TOKEN_MAX_RECLAIM_TIME = 351,
|
||||
TOKEN_UNWARNED_RECLAIM_CYCLES = 352,
|
||||
TOKEN_DHCP4O6_PORT = 353,
|
||||
TOKEN_CONTROL_SOCKET = 354,
|
||||
TOKEN_SOCKET_TYPE = 355,
|
||||
TOKEN_SOCKET_NAME = 356,
|
||||
TOKEN_DHCP_DDNS = 357,
|
||||
TOKEN_ENABLE_UPDATES = 358,
|
||||
TOKEN_QUALIFYING_SUFFIX = 359,
|
||||
TOKEN_SERVER_IP = 360,
|
||||
TOKEN_SERVER_PORT = 361,
|
||||
TOKEN_SENDER_IP = 362,
|
||||
TOKEN_SENDER_PORT = 363,
|
||||
TOKEN_MAX_QUEUE_SIZE = 364,
|
||||
TOKEN_NCR_PROTOCOL = 365,
|
||||
TOKEN_NCR_FORMAT = 366,
|
||||
TOKEN_ALWAYS_INCLUDE_FQDN = 367,
|
||||
TOKEN_OVERRIDE_NO_UPDATE = 368,
|
||||
TOKEN_OVERRIDE_CLIENT_UPDATE = 369,
|
||||
TOKEN_REPLACE_CLIENT_NAME = 370,
|
||||
TOKEN_GENERATED_PREFIX = 371,
|
||||
TOKEN_TCP = 372,
|
||||
TOKEN_JSON = 373,
|
||||
TOKEN_WHEN_PRESENT = 374,
|
||||
TOKEN_NEVER = 375,
|
||||
TOKEN_ALWAYS = 376,
|
||||
TOKEN_WHEN_NOT_PRESENT = 377,
|
||||
TOKEN_LOGGING = 378,
|
||||
TOKEN_LOGGERS = 379,
|
||||
TOKEN_OUTPUT_OPTIONS = 380,
|
||||
TOKEN_OUTPUT = 381,
|
||||
TOKEN_DEBUGLEVEL = 382,
|
||||
TOKEN_SEVERITY = 383,
|
||||
TOKEN_FLUSH = 384,
|
||||
TOKEN_MAXSIZE = 385,
|
||||
TOKEN_MAXVER = 386,
|
||||
TOKEN_DHCP6 = 387,
|
||||
TOKEN_DHCPDDNS = 388,
|
||||
TOKEN_CONTROL_AGENT = 389,
|
||||
TOKEN_TOPLEVEL_JSON = 390,
|
||||
TOKEN_TOPLEVEL_DHCP4 = 391,
|
||||
TOKEN_SUB_DHCP4 = 392,
|
||||
TOKEN_SUB_INTERFACES4 = 393,
|
||||
TOKEN_SUB_SUBNET4 = 394,
|
||||
TOKEN_SUB_POOL4 = 395,
|
||||
TOKEN_SUB_RESERVATION = 396,
|
||||
TOKEN_SUB_OPTION_DEFS = 397,
|
||||
TOKEN_SUB_OPTION_DEF = 398,
|
||||
TOKEN_SUB_OPTION_DATA = 399,
|
||||
TOKEN_SUB_HOOKS_LIBRARY = 400,
|
||||
TOKEN_SUB_DHCP_DDNS = 401,
|
||||
TOKEN_SUB_LOGGING = 402,
|
||||
TOKEN_STRING = 403,
|
||||
TOKEN_INTEGER = 404,
|
||||
TOKEN_FLOAT = 405,
|
||||
TOKEN_BOOLEAN = 406
|
||||
TOKEN_HOSTS_DATABASES = 282,
|
||||
TOKEN_TYPE = 283,
|
||||
TOKEN_MEMFILE = 284,
|
||||
TOKEN_MYSQL = 285,
|
||||
TOKEN_POSTGRESQL = 286,
|
||||
TOKEN_CQL = 287,
|
||||
TOKEN_USER = 288,
|
||||
TOKEN_PASSWORD = 289,
|
||||
TOKEN_HOST = 290,
|
||||
TOKEN_PORT = 291,
|
||||
TOKEN_PERSIST = 292,
|
||||
TOKEN_LFC_INTERVAL = 293,
|
||||
TOKEN_READONLY = 294,
|
||||
TOKEN_CONNECT_TIMEOUT = 295,
|
||||
TOKEN_CONTACT_POINTS = 296,
|
||||
TOKEN_KEYSPACE = 297,
|
||||
TOKEN_VALID_LIFETIME = 298,
|
||||
TOKEN_RENEW_TIMER = 299,
|
||||
TOKEN_REBIND_TIMER = 300,
|
||||
TOKEN_DECLINE_PROBATION_PERIOD = 301,
|
||||
TOKEN_SUBNET4 = 302,
|
||||
TOKEN_SUBNET_4O6_INTERFACE = 303,
|
||||
TOKEN_SUBNET_4O6_INTERFACE_ID = 304,
|
||||
TOKEN_SUBNET_4O6_SUBNET = 305,
|
||||
TOKEN_OPTION_DEF = 306,
|
||||
TOKEN_OPTION_DATA = 307,
|
||||
TOKEN_NAME = 308,
|
||||
TOKEN_DATA = 309,
|
||||
TOKEN_CODE = 310,
|
||||
TOKEN_SPACE = 311,
|
||||
TOKEN_CSV_FORMAT = 312,
|
||||
TOKEN_ALWAYS_SEND = 313,
|
||||
TOKEN_RECORD_TYPES = 314,
|
||||
TOKEN_ENCAPSULATE = 315,
|
||||
TOKEN_ARRAY = 316,
|
||||
TOKEN_SHARED_NETWORKS = 317,
|
||||
TOKEN_POOLS = 318,
|
||||
TOKEN_POOL = 319,
|
||||
TOKEN_USER_CONTEXT = 320,
|
||||
TOKEN_COMMENT = 321,
|
||||
TOKEN_SUBNET = 322,
|
||||
TOKEN_INTERFACE = 323,
|
||||
TOKEN_INTERFACE_ID = 324,
|
||||
TOKEN_ID = 325,
|
||||
TOKEN_RAPID_COMMIT = 326,
|
||||
TOKEN_RESERVATION_MODE = 327,
|
||||
TOKEN_DISABLED = 328,
|
||||
TOKEN_OUT_OF_POOL = 329,
|
||||
TOKEN_ALL = 330,
|
||||
TOKEN_HOST_RESERVATION_IDENTIFIERS = 331,
|
||||
TOKEN_CLIENT_CLASSES = 332,
|
||||
TOKEN_TEST = 333,
|
||||
TOKEN_CLIENT_CLASS = 334,
|
||||
TOKEN_RESERVATIONS = 335,
|
||||
TOKEN_DUID = 336,
|
||||
TOKEN_HW_ADDRESS = 337,
|
||||
TOKEN_CIRCUIT_ID = 338,
|
||||
TOKEN_CLIENT_ID = 339,
|
||||
TOKEN_HOSTNAME = 340,
|
||||
TOKEN_FLEX_ID = 341,
|
||||
TOKEN_RELAY = 342,
|
||||
TOKEN_IP_ADDRESS = 343,
|
||||
TOKEN_HOOKS_LIBRARIES = 344,
|
||||
TOKEN_LIBRARY = 345,
|
||||
TOKEN_PARAMETERS = 346,
|
||||
TOKEN_EXPIRED_LEASES_PROCESSING = 347,
|
||||
TOKEN_RECLAIM_TIMER_WAIT_TIME = 348,
|
||||
TOKEN_FLUSH_RECLAIMED_TIMER_WAIT_TIME = 349,
|
||||
TOKEN_HOLD_RECLAIMED_TIME = 350,
|
||||
TOKEN_MAX_RECLAIM_LEASES = 351,
|
||||
TOKEN_MAX_RECLAIM_TIME = 352,
|
||||
TOKEN_UNWARNED_RECLAIM_CYCLES = 353,
|
||||
TOKEN_DHCP4O6_PORT = 354,
|
||||
TOKEN_CONTROL_SOCKET = 355,
|
||||
TOKEN_SOCKET_TYPE = 356,
|
||||
TOKEN_SOCKET_NAME = 357,
|
||||
TOKEN_DHCP_DDNS = 358,
|
||||
TOKEN_ENABLE_UPDATES = 359,
|
||||
TOKEN_QUALIFYING_SUFFIX = 360,
|
||||
TOKEN_SERVER_IP = 361,
|
||||
TOKEN_SERVER_PORT = 362,
|
||||
TOKEN_SENDER_IP = 363,
|
||||
TOKEN_SENDER_PORT = 364,
|
||||
TOKEN_MAX_QUEUE_SIZE = 365,
|
||||
TOKEN_NCR_PROTOCOL = 366,
|
||||
TOKEN_NCR_FORMAT = 367,
|
||||
TOKEN_ALWAYS_INCLUDE_FQDN = 368,
|
||||
TOKEN_OVERRIDE_NO_UPDATE = 369,
|
||||
TOKEN_OVERRIDE_CLIENT_UPDATE = 370,
|
||||
TOKEN_REPLACE_CLIENT_NAME = 371,
|
||||
TOKEN_GENERATED_PREFIX = 372,
|
||||
TOKEN_TCP = 373,
|
||||
TOKEN_JSON = 374,
|
||||
TOKEN_WHEN_PRESENT = 375,
|
||||
TOKEN_NEVER = 376,
|
||||
TOKEN_ALWAYS = 377,
|
||||
TOKEN_WHEN_NOT_PRESENT = 378,
|
||||
TOKEN_LOGGING = 379,
|
||||
TOKEN_LOGGERS = 380,
|
||||
TOKEN_OUTPUT_OPTIONS = 381,
|
||||
TOKEN_OUTPUT = 382,
|
||||
TOKEN_DEBUGLEVEL = 383,
|
||||
TOKEN_SEVERITY = 384,
|
||||
TOKEN_FLUSH = 385,
|
||||
TOKEN_MAXSIZE = 386,
|
||||
TOKEN_MAXVER = 387,
|
||||
TOKEN_DHCP6 = 388,
|
||||
TOKEN_DHCPDDNS = 389,
|
||||
TOKEN_CONTROL_AGENT = 390,
|
||||
TOKEN_TOPLEVEL_JSON = 391,
|
||||
TOKEN_TOPLEVEL_DHCP4 = 392,
|
||||
TOKEN_SUB_DHCP4 = 393,
|
||||
TOKEN_SUB_INTERFACES4 = 394,
|
||||
TOKEN_SUB_SUBNET4 = 395,
|
||||
TOKEN_SUB_POOL4 = 396,
|
||||
TOKEN_SUB_RESERVATION = 397,
|
||||
TOKEN_SUB_OPTION_DEFS = 398,
|
||||
TOKEN_SUB_OPTION_DEF = 399,
|
||||
TOKEN_SUB_OPTION_DATA = 400,
|
||||
TOKEN_SUB_HOOKS_LIBRARY = 401,
|
||||
TOKEN_SUB_DHCP_DDNS = 402,
|
||||
TOKEN_SUB_LOGGING = 403,
|
||||
TOKEN_STRING = 404,
|
||||
TOKEN_INTEGER = 405,
|
||||
TOKEN_FLOAT = 406,
|
||||
TOKEN_BOOLEAN = 407
|
||||
};
|
||||
};
|
||||
|
||||
@ -711,6 +712,10 @@ namespace isc { namespace dhcp {
|
||||
symbol_type
|
||||
make_HOSTS_DATABASE (const location_type& l);
|
||||
|
||||
static inline
|
||||
symbol_type
|
||||
make_HOSTS_DATABASES (const location_type& l);
|
||||
|
||||
static inline
|
||||
symbol_type
|
||||
make_TYPE (const location_type& l);
|
||||
@ -1416,12 +1421,12 @@ namespace isc { namespace dhcp {
|
||||
enum
|
||||
{
|
||||
yyeof_ = 0,
|
||||
yylast_ = 886, ///< Last index in yytable_.
|
||||
yynnts_ = 338, ///< Number of nonterminal symbols.
|
||||
yylast_ = 903, ///< Last index in yytable_.
|
||||
yynnts_ = 344, ///< Number of nonterminal symbols.
|
||||
yyfinal_ = 28, ///< Termination state number.
|
||||
yyterror_ = 1,
|
||||
yyerrcode_ = 256,
|
||||
yyntokens_ = 152 ///< Number of tokens.
|
||||
yyntokens_ = 153 ///< Number of tokens.
|
||||
};
|
||||
|
||||
|
||||
@ -1478,9 +1483,9 @@ namespace isc { namespace dhcp {
|
||||
115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
|
||||
125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
|
||||
135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
|
||||
145, 146, 147, 148, 149, 150, 151
|
||||
145, 146, 147, 148, 149, 150, 151, 152
|
||||
};
|
||||
const unsigned int user_token_number_max_ = 406;
|
||||
const unsigned int user_token_number_max_ = 407;
|
||||
const token_number_type undef_token_ = 2;
|
||||
|
||||
if (static_cast<int>(t) <= yyeof_)
|
||||
@ -1513,30 +1518,30 @@ namespace isc { namespace dhcp {
|
||||
{
|
||||
switch (other.type_get ())
|
||||
{
|
||||
case 167: // value
|
||||
case 171: // map_value
|
||||
case 209: // socket_type
|
||||
case 212: // outbound_interface_value
|
||||
case 222: // db_type
|
||||
case 299: // hr_mode
|
||||
case 445: // ncr_protocol_value
|
||||
case 453: // replace_client_name_value
|
||||
case 168: // value
|
||||
case 172: // map_value
|
||||
case 210: // socket_type
|
||||
case 213: // outbound_interface_value
|
||||
case 229: // db_type
|
||||
case 306: // hr_mode
|
||||
case 452: // ncr_protocol_value
|
||||
case 460: // replace_client_name_value
|
||||
value.copy< ElementPtr > (other.value);
|
||||
break;
|
||||
|
||||
case 151: // "boolean"
|
||||
case 152: // "boolean"
|
||||
value.copy< bool > (other.value);
|
||||
break;
|
||||
|
||||
case 150: // "floating point"
|
||||
case 151: // "floating point"
|
||||
value.copy< double > (other.value);
|
||||
break;
|
||||
|
||||
case 149: // "integer"
|
||||
case 150: // "integer"
|
||||
value.copy< int64_t > (other.value);
|
||||
break;
|
||||
|
||||
case 148: // "constant string"
|
||||
case 149: // "constant string"
|
||||
value.copy< std::string > (other.value);
|
||||
break;
|
||||
|
||||
@ -1557,30 +1562,30 @@ namespace isc { namespace dhcp {
|
||||
(void) v;
|
||||
switch (this->type_get ())
|
||||
{
|
||||
case 167: // value
|
||||
case 171: // map_value
|
||||
case 209: // socket_type
|
||||
case 212: // outbound_interface_value
|
||||
case 222: // db_type
|
||||
case 299: // hr_mode
|
||||
case 445: // ncr_protocol_value
|
||||
case 453: // replace_client_name_value
|
||||
case 168: // value
|
||||
case 172: // map_value
|
||||
case 210: // socket_type
|
||||
case 213: // outbound_interface_value
|
||||
case 229: // db_type
|
||||
case 306: // hr_mode
|
||||
case 452: // ncr_protocol_value
|
||||
case 460: // replace_client_name_value
|
||||
value.copy< ElementPtr > (v);
|
||||
break;
|
||||
|
||||
case 151: // "boolean"
|
||||
case 152: // "boolean"
|
||||
value.copy< bool > (v);
|
||||
break;
|
||||
|
||||
case 150: // "floating point"
|
||||
case 151: // "floating point"
|
||||
value.copy< double > (v);
|
||||
break;
|
||||
|
||||
case 149: // "integer"
|
||||
case 150: // "integer"
|
||||
value.copy< int64_t > (v);
|
||||
break;
|
||||
|
||||
case 148: // "constant string"
|
||||
case 149: // "constant string"
|
||||
value.copy< std::string > (v);
|
||||
break;
|
||||
|
||||
@ -1660,30 +1665,30 @@ namespace isc { namespace dhcp {
|
||||
// Type destructor.
|
||||
switch (yytype)
|
||||
{
|
||||
case 167: // value
|
||||
case 171: // map_value
|
||||
case 209: // socket_type
|
||||
case 212: // outbound_interface_value
|
||||
case 222: // db_type
|
||||
case 299: // hr_mode
|
||||
case 445: // ncr_protocol_value
|
||||
case 453: // replace_client_name_value
|
||||
case 168: // value
|
||||
case 172: // map_value
|
||||
case 210: // socket_type
|
||||
case 213: // outbound_interface_value
|
||||
case 229: // db_type
|
||||
case 306: // hr_mode
|
||||
case 452: // ncr_protocol_value
|
||||
case 460: // replace_client_name_value
|
||||
value.template destroy< ElementPtr > ();
|
||||
break;
|
||||
|
||||
case 151: // "boolean"
|
||||
case 152: // "boolean"
|
||||
value.template destroy< bool > ();
|
||||
break;
|
||||
|
||||
case 150: // "floating point"
|
||||
case 151: // "floating point"
|
||||
value.template destroy< double > ();
|
||||
break;
|
||||
|
||||
case 149: // "integer"
|
||||
case 150: // "integer"
|
||||
value.template destroy< int64_t > ();
|
||||
break;
|
||||
|
||||
case 148: // "constant string"
|
||||
case 149: // "constant string"
|
||||
value.template destroy< std::string > ();
|
||||
break;
|
||||
|
||||
@ -1710,30 +1715,30 @@ namespace isc { namespace dhcp {
|
||||
super_type::move(s);
|
||||
switch (this->type_get ())
|
||||
{
|
||||
case 167: // value
|
||||
case 171: // map_value
|
||||
case 209: // socket_type
|
||||
case 212: // outbound_interface_value
|
||||
case 222: // db_type
|
||||
case 299: // hr_mode
|
||||
case 445: // ncr_protocol_value
|
||||
case 453: // replace_client_name_value
|
||||
case 168: // value
|
||||
case 172: // map_value
|
||||
case 210: // socket_type
|
||||
case 213: // outbound_interface_value
|
||||
case 229: // db_type
|
||||
case 306: // hr_mode
|
||||
case 452: // ncr_protocol_value
|
||||
case 460: // replace_client_name_value
|
||||
value.move< ElementPtr > (s.value);
|
||||
break;
|
||||
|
||||
case 151: // "boolean"
|
||||
case 152: // "boolean"
|
||||
value.move< bool > (s.value);
|
||||
break;
|
||||
|
||||
case 150: // "floating point"
|
||||
case 151: // "floating point"
|
||||
value.move< double > (s.value);
|
||||
break;
|
||||
|
||||
case 149: // "integer"
|
||||
case 150: // "integer"
|
||||
value.move< int64_t > (s.value);
|
||||
break;
|
||||
|
||||
case 148: // "constant string"
|
||||
case 149: // "constant string"
|
||||
value.move< std::string > (s.value);
|
||||
break;
|
||||
|
||||
@ -1807,7 +1812,7 @@ namespace isc { namespace dhcp {
|
||||
375, 376, 377, 378, 379, 380, 381, 382, 383, 384,
|
||||
385, 386, 387, 388, 389, 390, 391, 392, 393, 394,
|
||||
395, 396, 397, 398, 399, 400, 401, 402, 403, 404,
|
||||
405, 406
|
||||
405, 406, 407
|
||||
};
|
||||
return static_cast<token_type> (yytoken_number_[type]);
|
||||
}
|
||||
@ -1962,6 +1967,12 @@ namespace isc { namespace dhcp {
|
||||
return symbol_type (token::TOKEN_HOSTS_DATABASE, l);
|
||||
}
|
||||
|
||||
Dhcp4Parser::symbol_type
|
||||
Dhcp4Parser::make_HOSTS_DATABASES (const location_type& l)
|
||||
{
|
||||
return symbol_type (token::TOKEN_HOSTS_DATABASES, l);
|
||||
}
|
||||
|
||||
Dhcp4Parser::symbol_type
|
||||
Dhcp4Parser::make_TYPE (const location_type& l)
|
||||
{
|
||||
@ -2715,7 +2726,7 @@ namespace isc { namespace dhcp {
|
||||
|
||||
#line 14 "dhcp4_parser.yy" // lalr1.cc:377
|
||||
} } // isc::dhcp
|
||||
#line 2719 "dhcp4_parser.h" // lalr1.cc:377
|
||||
#line 2730 "dhcp4_parser.h" // lalr1.cc:377
|
||||
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
/* Copyright (C) 2016-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
|
||||
@ -68,6 +68,7 @@ using namespace std;
|
||||
|
||||
LEASE_DATABASE "lease-database"
|
||||
HOSTS_DATABASE "hosts-database"
|
||||
HOSTS_DATABASES "hosts-databases"
|
||||
TYPE "type"
|
||||
MEMFILE "memfile"
|
||||
MYSQL "mysql"
|
||||
@ -421,6 +422,7 @@ global_param: valid_lifetime
|
||||
| interfaces_config
|
||||
| lease_database
|
||||
| hosts_database
|
||||
| hosts_databases
|
||||
| host_reservation_identifiers
|
||||
| client_classes
|
||||
| option_def_list
|
||||
@ -568,6 +570,34 @@ hosts_database: HOSTS_DATABASE {
|
||||
ctx.leave();
|
||||
};
|
||||
|
||||
hosts_databases: HOSTS_DATABASES {
|
||||
ElementPtr l(new ListElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.back()->set("hosts-databases", l);
|
||||
ctx.stack_.push_back(l);
|
||||
ctx.enter(ctx.HOSTS_DATABASE);
|
||||
} COLON LSQUARE_BRACKET database_list RSQUARE_BRACKET {
|
||||
ctx.stack_.pop_back();
|
||||
ctx.leave();
|
||||
};
|
||||
|
||||
database_list: %empty
|
||||
| not_empty_database_list
|
||||
;
|
||||
|
||||
not_empty_database_list: database
|
||||
| not_empty_database_list COMMA database
|
||||
;
|
||||
|
||||
database: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.back()->add(m);
|
||||
ctx.stack_.push_back(m);
|
||||
} database_map_params RCURLY_BRACKET {
|
||||
// The type parameter is required
|
||||
ctx.require("type", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.stack_.pop_back();
|
||||
};
|
||||
|
||||
database_map_params: database_map_param
|
||||
| database_map_params COMMA database_map_param
|
||||
;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2012-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2012-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
|
||||
@ -412,19 +412,28 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set,
|
||||
|
||||
// Please move at the end when migration will be finished.
|
||||
if (config_pair.first == "lease-database") {
|
||||
DbAccessParser parser(DbAccessParser::LEASE_DB);
|
||||
DbAccessParser parser(CfgDbAccess::LEASE_DB);
|
||||
CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
|
||||
parser.parse(cfg_db_access, config_pair.second);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (config_pair.first == "hosts-database") {
|
||||
DbAccessParser parser(DbAccessParser::HOSTS_DB);
|
||||
DbAccessParser parser(CfgDbAccess::HOSTS_DB);
|
||||
CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
|
||||
parser.parse(cfg_db_access, config_pair.second);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (config_pair.first == "hosts-databases") {
|
||||
CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
|
||||
for (size_t i = 0; i < config_pair.second->size(); ++i) {
|
||||
DbAccessParser parser(CfgDbAccess::HOSTS_DB + i);
|
||||
parser.parse(cfg_db_access, config_pair.second->get(i));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (config_pair.first == "subnet4") {
|
||||
SrvConfigPtr srv_cfg = CfgMgr::instance().getStagingCfg();
|
||||
Subnets4ListConfigParser subnets_parser;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated 201801182315
|
||||
// Generated 201802120036
|
||||
// A Bison parser, made by GNU Bison 3.0.4.
|
||||
|
||||
// Locations for Bison parsers in C++
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2015-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
|
||||
@ -223,7 +223,7 @@ public:
|
||||
/// Used while parsing Dhcp4/lease-database structures.
|
||||
LEASE_DATABASE,
|
||||
|
||||
/// Used while parsing Dhcp4/hosts-database structures.
|
||||
/// Used while parsing Dhcp4/hosts-database[s] structures.
|
||||
HOSTS_DATABASE,
|
||||
|
||||
/// Used while parsing Dhcp4/*-database/type.
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated 201801182315
|
||||
// Generated 201802120036
|
||||
// A Bison parser, made by GNU Bison 3.0.4.
|
||||
|
||||
// Positions for Bison parsers in C++
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated 201801182315
|
||||
// Generated 201802120036
|
||||
// A Bison parser, made by GNU Bison 3.0.4.
|
||||
|
||||
// Stack handling for Bison parsers in C++
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2012-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2012-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
|
||||
@ -131,6 +131,28 @@ const char* PARSER_CONFIGS[] = {
|
||||
" } ]"
|
||||
"}",
|
||||
|
||||
// Configuration 4: two host databases
|
||||
"{"
|
||||
" \"interfaces-config\": {"
|
||||
" \"interfaces\": [\"*\" ]"
|
||||
" },"
|
||||
" \"valid-lifetime\": 4000,"
|
||||
" \"rebind-timer\": 2000,"
|
||||
" \"renew-timer\": 1000,"
|
||||
" \"hosts-databases\": [ {"
|
||||
" \"type\": \"mysql\","
|
||||
" \"name\": \"keatest1\","
|
||||
" \"user\": \"keatest\","
|
||||
" \"password\": \"keatest\""
|
||||
" },{"
|
||||
" \"type\": \"mysql\","
|
||||
" \"name\": \"keatest2\","
|
||||
" \"user\": \"keatest\","
|
||||
" \"password\": \"keatest\""
|
||||
" }"
|
||||
" ]"
|
||||
"}",
|
||||
|
||||
// Last Configuration for comments
|
||||
"{"
|
||||
" \"comment\": \"A DHCPv4 server\","
|
||||
@ -5757,10 +5779,28 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDeriveClientClass) {
|
||||
EXPECT_TRUE(classes.empty());
|
||||
}
|
||||
|
||||
// This test checks multiple host data sources.
|
||||
TEST_F(Dhcp4ParserTest, hostsDatabases) {
|
||||
|
||||
string config = PARSER_CONFIGS[4];
|
||||
extractConfig(config);
|
||||
configure(config, CONTROL_RESULT_SUCCESS, "");
|
||||
|
||||
// Check database config
|
||||
ConstCfgDbAccessPtr cfgdb =
|
||||
CfgMgr::instance().getStagingCfg()->getCfgDbAccess();
|
||||
ASSERT_TRUE(cfgdb);
|
||||
const std::vector<std::string>& hal = cfgdb->getHostDbAccessStringList();
|
||||
ASSERT_EQ(2, hal.size());
|
||||
// Keywords are in alphabetical order
|
||||
EXPECT_EQ("name=keatest1 password=keatest type=mysql user=keatest", hal[0]);
|
||||
EXPECT_EQ("name=keatest2 password=keatest type=mysql user=keatest", hal[1]);
|
||||
}
|
||||
|
||||
// This test checks comments. Please keep it last.
|
||||
TEST_F(Dhcp4ParserTest, comments) {
|
||||
|
||||
string config = PARSER_CONFIGS[4];
|
||||
string config = PARSER_CONFIGS[5];
|
||||
extractConfig(config);
|
||||
configure(config, CONTROL_RESULT_SUCCESS, "");
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 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
|
||||
@ -1719,6 +1719,30 @@ const char* EXTRACTED_CONFIGS[] = {
|
||||
" }\n",
|
||||
// CONFIGURATION 60
|
||||
"{\n"
|
||||
" \"hosts-databases\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"keatest1\",\n"
|
||||
" \"password\": \"keatest\",\n"
|
||||
" \"type\": \"mysql\",\n"
|
||||
" \"user\": \"keatest\"\n"
|
||||
" },\n"
|
||||
" {\n"
|
||||
" \"name\": \"keatest2\",\n"
|
||||
" \"password\": \"keatest\",\n"
|
||||
" \"type\": \"mysql\",\n"
|
||||
" \"user\": \"keatest\"\n"
|
||||
" }\n"
|
||||
" ],\n"
|
||||
" \"interfaces-config\": {\n"
|
||||
" \"interfaces\": [ \"*\" ],\n"
|
||||
" \"re-detect\": false\n"
|
||||
" },\n"
|
||||
" \"rebind-timer\": 2000,\n"
|
||||
" \"renew-timer\": 1000,\n"
|
||||
" \"valid-lifetime\": 4000\n"
|
||||
" }\n",
|
||||
// CONFIGURATION 61
|
||||
"{\n"
|
||||
" \"comment\": \"A DHCPv4 server\",\n"
|
||||
" \"client-classes\": [\n"
|
||||
" {\n"
|
||||
@ -6683,6 +6707,63 @@ const char* UNPARSED_CONFIGS[] = {
|
||||
" }\n",
|
||||
// CONFIGURATION 60
|
||||
"{\n"
|
||||
" \"decline-probation-period\": 86400,\n"
|
||||
" \"dhcp-ddns\": {\n"
|
||||
" \"always-include-fqdn\": false,\n"
|
||||
" \"enable-updates\": false,\n"
|
||||
" \"generated-prefix\": \"myhost\",\n"
|
||||
" \"max-queue-size\": 1024,\n"
|
||||
" \"ncr-format\": \"JSON\",\n"
|
||||
" \"ncr-protocol\": \"UDP\",\n"
|
||||
" \"override-client-update\": false,\n"
|
||||
" \"override-no-update\": false,\n"
|
||||
" \"qualifying-suffix\": \"\",\n"
|
||||
" \"replace-client-name\": \"never\",\n"
|
||||
" \"sender-ip\": \"0.0.0.0\",\n"
|
||||
" \"sender-port\": 0,\n"
|
||||
" \"server-ip\": \"127.0.0.1\",\n"
|
||||
" \"server-port\": 53001\n"
|
||||
" },\n"
|
||||
" \"dhcp4o6-port\": 0,\n"
|
||||
" \"echo-client-id\": true,\n"
|
||||
" \"expired-leases-processing\": {\n"
|
||||
" \"flush-reclaimed-timer-wait-time\": 25,\n"
|
||||
" \"hold-reclaimed-time\": 3600,\n"
|
||||
" \"max-reclaim-leases\": 100,\n"
|
||||
" \"max-reclaim-time\": 250,\n"
|
||||
" \"reclaim-timer-wait-time\": 10,\n"
|
||||
" \"unwarned-reclaim-cycles\": 5\n"
|
||||
" },\n"
|
||||
" \"hooks-libraries\": [ ],\n"
|
||||
" \"host-reservation-identifiers\": [ \"hw-address\", \"duid\", \"circuit-id\", \"client-id\" ],\n"
|
||||
" \"hosts-databases\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"keatest1\",\n"
|
||||
" \"password\": \"keatest\",\n"
|
||||
" \"type\": \"mysql\",\n"
|
||||
" \"user\": \"keatest\"\n"
|
||||
" },\n"
|
||||
" {\n"
|
||||
" \"name\": \"keatest2\",\n"
|
||||
" \"password\": \"keatest\",\n"
|
||||
" \"type\": \"mysql\",\n"
|
||||
" \"user\": \"keatest\"\n"
|
||||
" }\n"
|
||||
" ],\n"
|
||||
" \"interfaces-config\": {\n"
|
||||
" \"interfaces\": [ \"*\" ],\n"
|
||||
" \"re-detect\": false\n"
|
||||
" },\n"
|
||||
" \"lease-database\": {\n"
|
||||
" \"type\": \"memfile\"\n"
|
||||
" },\n"
|
||||
" \"option-data\": [ ],\n"
|
||||
" \"option-def\": [ ],\n"
|
||||
" \"shared-networks\": [ ],\n"
|
||||
" \"subnet4\": [ ]\n"
|
||||
" }\n",
|
||||
// CONFIGURATION 61
|
||||
"{\n"
|
||||
" \"comment\": \"A DHCPv4 server\",\n"
|
||||
" \"client-classes\": [\n"
|
||||
" {\n"
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 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
|
||||
@ -124,7 +124,7 @@ outputFormatted(const std::string& config) {
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
@ -155,9 +155,9 @@ extractConfig(const std::string& config) {
|
||||
++extract_count;
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
} // namespace test
|
||||
} // namespace dhcp
|
||||
} // namespace isc
|
||||
|
||||
namespace {
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
/* Copyright (C) 2016-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
|
||||
@ -457,6 +457,15 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
|
||||
}
|
||||
}
|
||||
|
||||
\"hosts-databases\" {
|
||||
switch(driver.ctx_) {
|
||||
case isc::dhcp::Parser6Context::DHCP6:
|
||||
return isc::dhcp::Dhcp6Parser::make_HOSTS_DATABASES(driver.loc_);
|
||||
default:
|
||||
return isc::dhcp::Dhcp6Parser::make_STRING("hosts-databases", driver.loc_);
|
||||
}
|
||||
}
|
||||
|
||||
\"readonly\" {
|
||||
switch(driver.ctx_) {
|
||||
case isc::dhcp::Parser6Context::HOSTS_DATABASE:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -360,147 +360,148 @@ namespace isc { namespace dhcp {
|
||||
TOKEN_RE_DETECT = 268,
|
||||
TOKEN_LEASE_DATABASE = 269,
|
||||
TOKEN_HOSTS_DATABASE = 270,
|
||||
TOKEN_TYPE = 271,
|
||||
TOKEN_MEMFILE = 272,
|
||||
TOKEN_MYSQL = 273,
|
||||
TOKEN_POSTGRESQL = 274,
|
||||
TOKEN_CQL = 275,
|
||||
TOKEN_USER = 276,
|
||||
TOKEN_PASSWORD = 277,
|
||||
TOKEN_HOST = 278,
|
||||
TOKEN_PORT = 279,
|
||||
TOKEN_PERSIST = 280,
|
||||
TOKEN_LFC_INTERVAL = 281,
|
||||
TOKEN_READONLY = 282,
|
||||
TOKEN_CONNECT_TIMEOUT = 283,
|
||||
TOKEN_CONTACT_POINTS = 284,
|
||||
TOKEN_KEYSPACE = 285,
|
||||
TOKEN_PREFERRED_LIFETIME = 286,
|
||||
TOKEN_VALID_LIFETIME = 287,
|
||||
TOKEN_RENEW_TIMER = 288,
|
||||
TOKEN_REBIND_TIMER = 289,
|
||||
TOKEN_DECLINE_PROBATION_PERIOD = 290,
|
||||
TOKEN_SUBNET6 = 291,
|
||||
TOKEN_OPTION_DEF = 292,
|
||||
TOKEN_OPTION_DATA = 293,
|
||||
TOKEN_NAME = 294,
|
||||
TOKEN_DATA = 295,
|
||||
TOKEN_CODE = 296,
|
||||
TOKEN_SPACE = 297,
|
||||
TOKEN_CSV_FORMAT = 298,
|
||||
TOKEN_ALWAYS_SEND = 299,
|
||||
TOKEN_RECORD_TYPES = 300,
|
||||
TOKEN_ENCAPSULATE = 301,
|
||||
TOKEN_ARRAY = 302,
|
||||
TOKEN_POOLS = 303,
|
||||
TOKEN_POOL = 304,
|
||||
TOKEN_PD_POOLS = 305,
|
||||
TOKEN_PREFIX = 306,
|
||||
TOKEN_PREFIX_LEN = 307,
|
||||
TOKEN_EXCLUDED_PREFIX = 308,
|
||||
TOKEN_EXCLUDED_PREFIX_LEN = 309,
|
||||
TOKEN_DELEGATED_LEN = 310,
|
||||
TOKEN_USER_CONTEXT = 311,
|
||||
TOKEN_COMMENT = 312,
|
||||
TOKEN_SUBNET = 313,
|
||||
TOKEN_INTERFACE = 314,
|
||||
TOKEN_INTERFACE_ID = 315,
|
||||
TOKEN_ID = 316,
|
||||
TOKEN_RAPID_COMMIT = 317,
|
||||
TOKEN_RESERVATION_MODE = 318,
|
||||
TOKEN_DISABLED = 319,
|
||||
TOKEN_OUT_OF_POOL = 320,
|
||||
TOKEN_ALL = 321,
|
||||
TOKEN_SHARED_NETWORKS = 322,
|
||||
TOKEN_MAC_SOURCES = 323,
|
||||
TOKEN_RELAY_SUPPLIED_OPTIONS = 324,
|
||||
TOKEN_HOST_RESERVATION_IDENTIFIERS = 325,
|
||||
TOKEN_CLIENT_CLASSES = 326,
|
||||
TOKEN_TEST = 327,
|
||||
TOKEN_CLIENT_CLASS = 328,
|
||||
TOKEN_RESERVATIONS = 329,
|
||||
TOKEN_IP_ADDRESSES = 330,
|
||||
TOKEN_PREFIXES = 331,
|
||||
TOKEN_DUID = 332,
|
||||
TOKEN_HW_ADDRESS = 333,
|
||||
TOKEN_HOSTNAME = 334,
|
||||
TOKEN_FLEX_ID = 335,
|
||||
TOKEN_RELAY = 336,
|
||||
TOKEN_IP_ADDRESS = 337,
|
||||
TOKEN_HOOKS_LIBRARIES = 338,
|
||||
TOKEN_LIBRARY = 339,
|
||||
TOKEN_PARAMETERS = 340,
|
||||
TOKEN_EXPIRED_LEASES_PROCESSING = 341,
|
||||
TOKEN_RECLAIM_TIMER_WAIT_TIME = 342,
|
||||
TOKEN_FLUSH_RECLAIMED_TIMER_WAIT_TIME = 343,
|
||||
TOKEN_HOLD_RECLAIMED_TIME = 344,
|
||||
TOKEN_MAX_RECLAIM_LEASES = 345,
|
||||
TOKEN_MAX_RECLAIM_TIME = 346,
|
||||
TOKEN_UNWARNED_RECLAIM_CYCLES = 347,
|
||||
TOKEN_SERVER_ID = 348,
|
||||
TOKEN_LLT = 349,
|
||||
TOKEN_EN = 350,
|
||||
TOKEN_LL = 351,
|
||||
TOKEN_IDENTIFIER = 352,
|
||||
TOKEN_HTYPE = 353,
|
||||
TOKEN_TIME = 354,
|
||||
TOKEN_ENTERPRISE_ID = 355,
|
||||
TOKEN_DHCP4O6_PORT = 356,
|
||||
TOKEN_CONTROL_SOCKET = 357,
|
||||
TOKEN_SOCKET_TYPE = 358,
|
||||
TOKEN_SOCKET_NAME = 359,
|
||||
TOKEN_DHCP_DDNS = 360,
|
||||
TOKEN_ENABLE_UPDATES = 361,
|
||||
TOKEN_QUALIFYING_SUFFIX = 362,
|
||||
TOKEN_SERVER_IP = 363,
|
||||
TOKEN_SERVER_PORT = 364,
|
||||
TOKEN_SENDER_IP = 365,
|
||||
TOKEN_SENDER_PORT = 366,
|
||||
TOKEN_MAX_QUEUE_SIZE = 367,
|
||||
TOKEN_NCR_PROTOCOL = 368,
|
||||
TOKEN_NCR_FORMAT = 369,
|
||||
TOKEN_ALWAYS_INCLUDE_FQDN = 370,
|
||||
TOKEN_OVERRIDE_NO_UPDATE = 371,
|
||||
TOKEN_OVERRIDE_CLIENT_UPDATE = 372,
|
||||
TOKEN_REPLACE_CLIENT_NAME = 373,
|
||||
TOKEN_GENERATED_PREFIX = 374,
|
||||
TOKEN_UDP = 375,
|
||||
TOKEN_TCP = 376,
|
||||
TOKEN_JSON = 377,
|
||||
TOKEN_WHEN_PRESENT = 378,
|
||||
TOKEN_NEVER = 379,
|
||||
TOKEN_ALWAYS = 380,
|
||||
TOKEN_WHEN_NOT_PRESENT = 381,
|
||||
TOKEN_LOGGING = 382,
|
||||
TOKEN_LOGGERS = 383,
|
||||
TOKEN_OUTPUT_OPTIONS = 384,
|
||||
TOKEN_OUTPUT = 385,
|
||||
TOKEN_DEBUGLEVEL = 386,
|
||||
TOKEN_SEVERITY = 387,
|
||||
TOKEN_FLUSH = 388,
|
||||
TOKEN_MAXSIZE = 389,
|
||||
TOKEN_MAXVER = 390,
|
||||
TOKEN_DHCP4 = 391,
|
||||
TOKEN_DHCPDDNS = 392,
|
||||
TOKEN_CONTROL_AGENT = 393,
|
||||
TOKEN_TOPLEVEL_JSON = 394,
|
||||
TOKEN_TOPLEVEL_DHCP6 = 395,
|
||||
TOKEN_SUB_DHCP6 = 396,
|
||||
TOKEN_SUB_INTERFACES6 = 397,
|
||||
TOKEN_SUB_SUBNET6 = 398,
|
||||
TOKEN_SUB_POOL6 = 399,
|
||||
TOKEN_SUB_PD_POOL = 400,
|
||||
TOKEN_SUB_RESERVATION = 401,
|
||||
TOKEN_SUB_OPTION_DEFS = 402,
|
||||
TOKEN_SUB_OPTION_DEF = 403,
|
||||
TOKEN_SUB_OPTION_DATA = 404,
|
||||
TOKEN_SUB_HOOKS_LIBRARY = 405,
|
||||
TOKEN_SUB_DHCP_DDNS = 406,
|
||||
TOKEN_SUB_LOGGING = 407,
|
||||
TOKEN_STRING = 408,
|
||||
TOKEN_INTEGER = 409,
|
||||
TOKEN_FLOAT = 410,
|
||||
TOKEN_BOOLEAN = 411
|
||||
TOKEN_HOSTS_DATABASES = 271,
|
||||
TOKEN_TYPE = 272,
|
||||
TOKEN_MEMFILE = 273,
|
||||
TOKEN_MYSQL = 274,
|
||||
TOKEN_POSTGRESQL = 275,
|
||||
TOKEN_CQL = 276,
|
||||
TOKEN_USER = 277,
|
||||
TOKEN_PASSWORD = 278,
|
||||
TOKEN_HOST = 279,
|
||||
TOKEN_PORT = 280,
|
||||
TOKEN_PERSIST = 281,
|
||||
TOKEN_LFC_INTERVAL = 282,
|
||||
TOKEN_READONLY = 283,
|
||||
TOKEN_CONNECT_TIMEOUT = 284,
|
||||
TOKEN_CONTACT_POINTS = 285,
|
||||
TOKEN_KEYSPACE = 286,
|
||||
TOKEN_PREFERRED_LIFETIME = 287,
|
||||
TOKEN_VALID_LIFETIME = 288,
|
||||
TOKEN_RENEW_TIMER = 289,
|
||||
TOKEN_REBIND_TIMER = 290,
|
||||
TOKEN_DECLINE_PROBATION_PERIOD = 291,
|
||||
TOKEN_SUBNET6 = 292,
|
||||
TOKEN_OPTION_DEF = 293,
|
||||
TOKEN_OPTION_DATA = 294,
|
||||
TOKEN_NAME = 295,
|
||||
TOKEN_DATA = 296,
|
||||
TOKEN_CODE = 297,
|
||||
TOKEN_SPACE = 298,
|
||||
TOKEN_CSV_FORMAT = 299,
|
||||
TOKEN_ALWAYS_SEND = 300,
|
||||
TOKEN_RECORD_TYPES = 301,
|
||||
TOKEN_ENCAPSULATE = 302,
|
||||
TOKEN_ARRAY = 303,
|
||||
TOKEN_POOLS = 304,
|
||||
TOKEN_POOL = 305,
|
||||
TOKEN_PD_POOLS = 306,
|
||||
TOKEN_PREFIX = 307,
|
||||
TOKEN_PREFIX_LEN = 308,
|
||||
TOKEN_EXCLUDED_PREFIX = 309,
|
||||
TOKEN_EXCLUDED_PREFIX_LEN = 310,
|
||||
TOKEN_DELEGATED_LEN = 311,
|
||||
TOKEN_USER_CONTEXT = 312,
|
||||
TOKEN_COMMENT = 313,
|
||||
TOKEN_SUBNET = 314,
|
||||
TOKEN_INTERFACE = 315,
|
||||
TOKEN_INTERFACE_ID = 316,
|
||||
TOKEN_ID = 317,
|
||||
TOKEN_RAPID_COMMIT = 318,
|
||||
TOKEN_RESERVATION_MODE = 319,
|
||||
TOKEN_DISABLED = 320,
|
||||
TOKEN_OUT_OF_POOL = 321,
|
||||
TOKEN_ALL = 322,
|
||||
TOKEN_SHARED_NETWORKS = 323,
|
||||
TOKEN_MAC_SOURCES = 324,
|
||||
TOKEN_RELAY_SUPPLIED_OPTIONS = 325,
|
||||
TOKEN_HOST_RESERVATION_IDENTIFIERS = 326,
|
||||
TOKEN_CLIENT_CLASSES = 327,
|
||||
TOKEN_TEST = 328,
|
||||
TOKEN_CLIENT_CLASS = 329,
|
||||
TOKEN_RESERVATIONS = 330,
|
||||
TOKEN_IP_ADDRESSES = 331,
|
||||
TOKEN_PREFIXES = 332,
|
||||
TOKEN_DUID = 333,
|
||||
TOKEN_HW_ADDRESS = 334,
|
||||
TOKEN_HOSTNAME = 335,
|
||||
TOKEN_FLEX_ID = 336,
|
||||
TOKEN_RELAY = 337,
|
||||
TOKEN_IP_ADDRESS = 338,
|
||||
TOKEN_HOOKS_LIBRARIES = 339,
|
||||
TOKEN_LIBRARY = 340,
|
||||
TOKEN_PARAMETERS = 341,
|
||||
TOKEN_EXPIRED_LEASES_PROCESSING = 342,
|
||||
TOKEN_RECLAIM_TIMER_WAIT_TIME = 343,
|
||||
TOKEN_FLUSH_RECLAIMED_TIMER_WAIT_TIME = 344,
|
||||
TOKEN_HOLD_RECLAIMED_TIME = 345,
|
||||
TOKEN_MAX_RECLAIM_LEASES = 346,
|
||||
TOKEN_MAX_RECLAIM_TIME = 347,
|
||||
TOKEN_UNWARNED_RECLAIM_CYCLES = 348,
|
||||
TOKEN_SERVER_ID = 349,
|
||||
TOKEN_LLT = 350,
|
||||
TOKEN_EN = 351,
|
||||
TOKEN_LL = 352,
|
||||
TOKEN_IDENTIFIER = 353,
|
||||
TOKEN_HTYPE = 354,
|
||||
TOKEN_TIME = 355,
|
||||
TOKEN_ENTERPRISE_ID = 356,
|
||||
TOKEN_DHCP4O6_PORT = 357,
|
||||
TOKEN_CONTROL_SOCKET = 358,
|
||||
TOKEN_SOCKET_TYPE = 359,
|
||||
TOKEN_SOCKET_NAME = 360,
|
||||
TOKEN_DHCP_DDNS = 361,
|
||||
TOKEN_ENABLE_UPDATES = 362,
|
||||
TOKEN_QUALIFYING_SUFFIX = 363,
|
||||
TOKEN_SERVER_IP = 364,
|
||||
TOKEN_SERVER_PORT = 365,
|
||||
TOKEN_SENDER_IP = 366,
|
||||
TOKEN_SENDER_PORT = 367,
|
||||
TOKEN_MAX_QUEUE_SIZE = 368,
|
||||
TOKEN_NCR_PROTOCOL = 369,
|
||||
TOKEN_NCR_FORMAT = 370,
|
||||
TOKEN_ALWAYS_INCLUDE_FQDN = 371,
|
||||
TOKEN_OVERRIDE_NO_UPDATE = 372,
|
||||
TOKEN_OVERRIDE_CLIENT_UPDATE = 373,
|
||||
TOKEN_REPLACE_CLIENT_NAME = 374,
|
||||
TOKEN_GENERATED_PREFIX = 375,
|
||||
TOKEN_UDP = 376,
|
||||
TOKEN_TCP = 377,
|
||||
TOKEN_JSON = 378,
|
||||
TOKEN_WHEN_PRESENT = 379,
|
||||
TOKEN_NEVER = 380,
|
||||
TOKEN_ALWAYS = 381,
|
||||
TOKEN_WHEN_NOT_PRESENT = 382,
|
||||
TOKEN_LOGGING = 383,
|
||||
TOKEN_LOGGERS = 384,
|
||||
TOKEN_OUTPUT_OPTIONS = 385,
|
||||
TOKEN_OUTPUT = 386,
|
||||
TOKEN_DEBUGLEVEL = 387,
|
||||
TOKEN_SEVERITY = 388,
|
||||
TOKEN_FLUSH = 389,
|
||||
TOKEN_MAXSIZE = 390,
|
||||
TOKEN_MAXVER = 391,
|
||||
TOKEN_DHCP4 = 392,
|
||||
TOKEN_DHCPDDNS = 393,
|
||||
TOKEN_CONTROL_AGENT = 394,
|
||||
TOKEN_TOPLEVEL_JSON = 395,
|
||||
TOKEN_TOPLEVEL_DHCP6 = 396,
|
||||
TOKEN_SUB_DHCP6 = 397,
|
||||
TOKEN_SUB_INTERFACES6 = 398,
|
||||
TOKEN_SUB_SUBNET6 = 399,
|
||||
TOKEN_SUB_POOL6 = 400,
|
||||
TOKEN_SUB_PD_POOL = 401,
|
||||
TOKEN_SUB_RESERVATION = 402,
|
||||
TOKEN_SUB_OPTION_DEFS = 403,
|
||||
TOKEN_SUB_OPTION_DEF = 404,
|
||||
TOKEN_SUB_OPTION_DATA = 405,
|
||||
TOKEN_SUB_HOOKS_LIBRARY = 406,
|
||||
TOKEN_SUB_DHCP_DDNS = 407,
|
||||
TOKEN_SUB_LOGGING = 408,
|
||||
TOKEN_STRING = 409,
|
||||
TOKEN_INTEGER = 410,
|
||||
TOKEN_FLOAT = 411,
|
||||
TOKEN_BOOLEAN = 412
|
||||
};
|
||||
};
|
||||
|
||||
@ -671,6 +672,10 @@ namespace isc { namespace dhcp {
|
||||
symbol_type
|
||||
make_HOSTS_DATABASE (const location_type& l);
|
||||
|
||||
static inline
|
||||
symbol_type
|
||||
make_HOSTS_DATABASES (const location_type& l);
|
||||
|
||||
static inline
|
||||
symbol_type
|
||||
make_TYPE (const location_type& l);
|
||||
@ -1440,12 +1445,12 @@ namespace isc { namespace dhcp {
|
||||
enum
|
||||
{
|
||||
yyeof_ = 0,
|
||||
yylast_ = 931, ///< Last index in yytable_.
|
||||
yynnts_ = 352, ///< Number of nonterminal symbols.
|
||||
yylast_ = 933, ///< Last index in yytable_.
|
||||
yynnts_ = 358, ///< Number of nonterminal symbols.
|
||||
yyfinal_ = 30, ///< Termination state number.
|
||||
yyterror_ = 1,
|
||||
yyerrcode_ = 256,
|
||||
yyntokens_ = 157 ///< Number of tokens.
|
||||
yyntokens_ = 158 ///< Number of tokens.
|
||||
};
|
||||
|
||||
|
||||
@ -1503,9 +1508,9 @@ namespace isc { namespace dhcp {
|
||||
125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
|
||||
135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
|
||||
145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
|
||||
155, 156
|
||||
155, 156, 157
|
||||
};
|
||||
const unsigned int user_token_number_max_ = 411;
|
||||
const unsigned int user_token_number_max_ = 412;
|
||||
const token_number_type undef_token_ = 2;
|
||||
|
||||
if (static_cast<int>(t) <= yyeof_)
|
||||
@ -1538,29 +1543,29 @@ namespace isc { namespace dhcp {
|
||||
{
|
||||
switch (other.type_get ())
|
||||
{
|
||||
case 173: // value
|
||||
case 177: // map_value
|
||||
case 221: // db_type
|
||||
case 297: // hr_mode
|
||||
case 431: // duid_type
|
||||
case 464: // ncr_protocol_value
|
||||
case 472: // replace_client_name_value
|
||||
case 174: // value
|
||||
case 178: // map_value
|
||||
case 228: // db_type
|
||||
case 304: // hr_mode
|
||||
case 438: // duid_type
|
||||
case 471: // ncr_protocol_value
|
||||
case 479: // replace_client_name_value
|
||||
value.copy< ElementPtr > (other.value);
|
||||
break;
|
||||
|
||||
case 156: // "boolean"
|
||||
case 157: // "boolean"
|
||||
value.copy< bool > (other.value);
|
||||
break;
|
||||
|
||||
case 155: // "floating point"
|
||||
case 156: // "floating point"
|
||||
value.copy< double > (other.value);
|
||||
break;
|
||||
|
||||
case 154: // "integer"
|
||||
case 155: // "integer"
|
||||
value.copy< int64_t > (other.value);
|
||||
break;
|
||||
|
||||
case 153: // "constant string"
|
||||
case 154: // "constant string"
|
||||
value.copy< std::string > (other.value);
|
||||
break;
|
||||
|
||||
@ -1581,29 +1586,29 @@ namespace isc { namespace dhcp {
|
||||
(void) v;
|
||||
switch (this->type_get ())
|
||||
{
|
||||
case 173: // value
|
||||
case 177: // map_value
|
||||
case 221: // db_type
|
||||
case 297: // hr_mode
|
||||
case 431: // duid_type
|
||||
case 464: // ncr_protocol_value
|
||||
case 472: // replace_client_name_value
|
||||
case 174: // value
|
||||
case 178: // map_value
|
||||
case 228: // db_type
|
||||
case 304: // hr_mode
|
||||
case 438: // duid_type
|
||||
case 471: // ncr_protocol_value
|
||||
case 479: // replace_client_name_value
|
||||
value.copy< ElementPtr > (v);
|
||||
break;
|
||||
|
||||
case 156: // "boolean"
|
||||
case 157: // "boolean"
|
||||
value.copy< bool > (v);
|
||||
break;
|
||||
|
||||
case 155: // "floating point"
|
||||
case 156: // "floating point"
|
||||
value.copy< double > (v);
|
||||
break;
|
||||
|
||||
case 154: // "integer"
|
||||
case 155: // "integer"
|
||||
value.copy< int64_t > (v);
|
||||
break;
|
||||
|
||||
case 153: // "constant string"
|
||||
case 154: // "constant string"
|
||||
value.copy< std::string > (v);
|
||||
break;
|
||||
|
||||
@ -1683,29 +1688,29 @@ namespace isc { namespace dhcp {
|
||||
// Type destructor.
|
||||
switch (yytype)
|
||||
{
|
||||
case 173: // value
|
||||
case 177: // map_value
|
||||
case 221: // db_type
|
||||
case 297: // hr_mode
|
||||
case 431: // duid_type
|
||||
case 464: // ncr_protocol_value
|
||||
case 472: // replace_client_name_value
|
||||
case 174: // value
|
||||
case 178: // map_value
|
||||
case 228: // db_type
|
||||
case 304: // hr_mode
|
||||
case 438: // duid_type
|
||||
case 471: // ncr_protocol_value
|
||||
case 479: // replace_client_name_value
|
||||
value.template destroy< ElementPtr > ();
|
||||
break;
|
||||
|
||||
case 156: // "boolean"
|
||||
case 157: // "boolean"
|
||||
value.template destroy< bool > ();
|
||||
break;
|
||||
|
||||
case 155: // "floating point"
|
||||
case 156: // "floating point"
|
||||
value.template destroy< double > ();
|
||||
break;
|
||||
|
||||
case 154: // "integer"
|
||||
case 155: // "integer"
|
||||
value.template destroy< int64_t > ();
|
||||
break;
|
||||
|
||||
case 153: // "constant string"
|
||||
case 154: // "constant string"
|
||||
value.template destroy< std::string > ();
|
||||
break;
|
||||
|
||||
@ -1732,29 +1737,29 @@ namespace isc { namespace dhcp {
|
||||
super_type::move(s);
|
||||
switch (this->type_get ())
|
||||
{
|
||||
case 173: // value
|
||||
case 177: // map_value
|
||||
case 221: // db_type
|
||||
case 297: // hr_mode
|
||||
case 431: // duid_type
|
||||
case 464: // ncr_protocol_value
|
||||
case 472: // replace_client_name_value
|
||||
case 174: // value
|
||||
case 178: // map_value
|
||||
case 228: // db_type
|
||||
case 304: // hr_mode
|
||||
case 438: // duid_type
|
||||
case 471: // ncr_protocol_value
|
||||
case 479: // replace_client_name_value
|
||||
value.move< ElementPtr > (s.value);
|
||||
break;
|
||||
|
||||
case 156: // "boolean"
|
||||
case 157: // "boolean"
|
||||
value.move< bool > (s.value);
|
||||
break;
|
||||
|
||||
case 155: // "floating point"
|
||||
case 156: // "floating point"
|
||||
value.move< double > (s.value);
|
||||
break;
|
||||
|
||||
case 154: // "integer"
|
||||
case 155: // "integer"
|
||||
value.move< int64_t > (s.value);
|
||||
break;
|
||||
|
||||
case 153: // "constant string"
|
||||
case 154: // "constant string"
|
||||
value.move< std::string > (s.value);
|
||||
break;
|
||||
|
||||
@ -1828,7 +1833,7 @@ namespace isc { namespace dhcp {
|
||||
375, 376, 377, 378, 379, 380, 381, 382, 383, 384,
|
||||
385, 386, 387, 388, 389, 390, 391, 392, 393, 394,
|
||||
395, 396, 397, 398, 399, 400, 401, 402, 403, 404,
|
||||
405, 406, 407, 408, 409, 410, 411
|
||||
405, 406, 407, 408, 409, 410, 411, 412
|
||||
};
|
||||
return static_cast<token_type> (yytoken_number_[type]);
|
||||
}
|
||||
@ -1917,6 +1922,12 @@ namespace isc { namespace dhcp {
|
||||
return symbol_type (token::TOKEN_HOSTS_DATABASE, l);
|
||||
}
|
||||
|
||||
Dhcp6Parser::symbol_type
|
||||
Dhcp6Parser::make_HOSTS_DATABASES (const location_type& l)
|
||||
{
|
||||
return symbol_type (token::TOKEN_HOSTS_DATABASES, l);
|
||||
}
|
||||
|
||||
Dhcp6Parser::symbol_type
|
||||
Dhcp6Parser::make_TYPE (const location_type& l)
|
||||
{
|
||||
@ -2766,7 +2777,7 @@ namespace isc { namespace dhcp {
|
||||
|
||||
#line 14 "dhcp6_parser.yy" // lalr1.cc:377
|
||||
} } // isc::dhcp
|
||||
#line 2770 "dhcp6_parser.h" // lalr1.cc:377
|
||||
#line 2781 "dhcp6_parser.h" // lalr1.cc:377
|
||||
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
/* Copyright (C) 2016-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
|
||||
@ -56,6 +56,7 @@ using namespace std;
|
||||
|
||||
LEASE_DATABASE "lease-database"
|
||||
HOSTS_DATABASE "hosts-database"
|
||||
HOSTS_DATABASES "hosts-databases"
|
||||
TYPE "type"
|
||||
MEMFILE "memfile"
|
||||
MYSQL "mysql"
|
||||
@ -425,6 +426,7 @@ global_param: preferred_lifetime
|
||||
| interfaces_config
|
||||
| lease_database
|
||||
| hosts_database
|
||||
| hosts_databases
|
||||
| mac_sources
|
||||
| relay_supplied_options
|
||||
| host_reservation_identifiers
|
||||
@ -538,6 +540,34 @@ hosts_database: HOSTS_DATABASE {
|
||||
ctx.leave();
|
||||
};
|
||||
|
||||
hosts_databases: HOSTS_DATABASES {
|
||||
ElementPtr l(new ListElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.back()->set("hosts-databases", l);
|
||||
ctx.stack_.push_back(l);
|
||||
ctx.enter(ctx.HOSTS_DATABASE);
|
||||
} COLON LSQUARE_BRACKET database_list RSQUARE_BRACKET {
|
||||
ctx.stack_.pop_back();
|
||||
ctx.leave();
|
||||
};
|
||||
|
||||
database_list: %empty
|
||||
| not_empty_database_list
|
||||
;
|
||||
|
||||
not_empty_database_list: database
|
||||
| not_empty_database_list COMMA database
|
||||
;
|
||||
|
||||
database: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.back()->add(m);
|
||||
ctx.stack_.push_back(m);
|
||||
} database_map_params RCURLY_BRACKET {
|
||||
// The type parameter is required
|
||||
ctx.require("type", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.stack_.pop_back();
|
||||
};
|
||||
|
||||
database_map_params: database_map_param
|
||||
| database_map_params COMMA database_map_param
|
||||
;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2012-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2012-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
|
||||
@ -525,19 +525,29 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set,
|
||||
|
||||
// Please move at the end when migration will be finished.
|
||||
if (config_pair.first == "lease-database") {
|
||||
DbAccessParser parser(DbAccessParser::LEASE_DB);
|
||||
DbAccessParser parser(CfgDbAccess::LEASE_DB);
|
||||
CfgDbAccessPtr cfg_db_access = srv_config->getCfgDbAccess();
|
||||
parser.parse(cfg_db_access, config_pair.second);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (config_pair.first == "hosts-database") {
|
||||
DbAccessParser parser(DbAccessParser::HOSTS_DB);
|
||||
DbAccessParser parser(CfgDbAccess::HOSTS_DB);
|
||||
CfgDbAccessPtr cfg_db_access = srv_config->getCfgDbAccess();
|
||||
parser.parse(cfg_db_access, config_pair.second);
|
||||
continue;
|
||||
}
|
||||
|
||||
// For now only support empty or singleton, ignoring extra entries.
|
||||
if (config_pair.first == "hosts-databases") {
|
||||
CfgDbAccessPtr cfg_db_access = srv_config->getCfgDbAccess();
|
||||
for (size_t i = 0; i < config_pair.second->size(); ++i) {
|
||||
DbAccessParser parser(CfgDbAccess::HOSTS_DB + i);
|
||||
parser.parse(cfg_db_access, config_pair.second->get(i));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (config_pair.first == "subnet6") {
|
||||
Subnets6ListConfigParser subnets_parser;
|
||||
// parse() returns number of subnets parsed. We may log it one day.
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated 201801182315
|
||||
// Generated 201802120036
|
||||
// A Bison parser, made by GNU Bison 3.0.4.
|
||||
|
||||
// Locations for Bison parsers in C++
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2015-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
|
||||
@ -221,7 +221,7 @@ public:
|
||||
/// Used while parsing Dhcp6/lease-database structures.
|
||||
LEASE_DATABASE,
|
||||
|
||||
/// Used while parsing Dhcp6/hosts-database structures.
|
||||
/// Used while parsing Dhcp6/hosts-database[s] structures.
|
||||
HOSTS_DATABASE,
|
||||
|
||||
/// Used while parsing Dhcp6/*-database/type.
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated 201801182315
|
||||
// Generated 201802120036
|
||||
// A Bison parser, made by GNU Bison 3.0.4.
|
||||
|
||||
// Positions for Bison parsers in C++
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated 201801182315
|
||||
// Generated 201802120036
|
||||
// A Bison parser, made by GNU Bison 3.0.4.
|
||||
|
||||
// Stack handling for Bison parsers in C++
|
||||
|
@ -208,6 +208,29 @@ const char* PARSER_CONFIGS[] = {
|
||||
" } ]"
|
||||
"}",
|
||||
|
||||
// Configuration 7: two host databases
|
||||
"{"
|
||||
" \"interfaces-config\": {"
|
||||
" \"interfaces\": [\"*\" ]"
|
||||
" },"
|
||||
" \"valid-lifetime\": 4000,"
|
||||
" \"preferred-lifetime\": 3000,"
|
||||
" \"rebind-timer\": 2000,"
|
||||
" \"renew-timer\": 1000,"
|
||||
" \"hosts-databases\": [ {"
|
||||
" \"type\": \"mysql\","
|
||||
" \"name\": \"keatest1\","
|
||||
" \"user\": \"keatest\","
|
||||
" \"password\": \"keatest\""
|
||||
" },{"
|
||||
" \"type\": \"mysql\","
|
||||
" \"name\": \"keatest2\","
|
||||
" \"user\": \"keatest\","
|
||||
" \"password\": \"keatest\""
|
||||
" }"
|
||||
" ]"
|
||||
"}",
|
||||
|
||||
// Last configuration for comments
|
||||
"{"
|
||||
" \"comment\": \"A DHCPv6 server\","
|
||||
@ -6314,10 +6337,28 @@ TEST_F(Dhcp6ParserTest, sharedNetworksRapidCommitMix) {
|
||||
"shared-network or the shared-network itself used rapid-commit true");
|
||||
}
|
||||
|
||||
// This test checks multiple host data sources.
|
||||
TEST_F(Dhcp6ParserTest, hostsDatabases) {
|
||||
|
||||
string config = PARSER_CONFIGS[7];
|
||||
extractConfig(config);
|
||||
configure(config, CONTROL_RESULT_SUCCESS, "");
|
||||
|
||||
// Check database config
|
||||
ConstCfgDbAccessPtr cfgdb =
|
||||
CfgMgr::instance().getStagingCfg()->getCfgDbAccess();
|
||||
ASSERT_TRUE(cfgdb);
|
||||
const std::vector<std::string>& hal = cfgdb->getHostDbAccessStringList();
|
||||
ASSERT_EQ(2, hal.size());
|
||||
// Keywords are in alphabetical order
|
||||
EXPECT_EQ("name=keatest1 password=keatest type=mysql user=keatest", hal[0]);
|
||||
EXPECT_EQ("name=keatest2 password=keatest type=mysql user=keatest", hal[1]);
|
||||
}
|
||||
|
||||
// This test checks comments. Please keep it last.
|
||||
TEST_F(Dhcp6ParserTest, comments) {
|
||||
|
||||
string config = PARSER_CONFIGS[7];
|
||||
string config = PARSER_CONFIGS[8];
|
||||
extractConfig(config);
|
||||
configure(config, CONTROL_RESULT_SUCCESS, "");
|
||||
|
||||
|
@ -1584,6 +1584,31 @@ const char* EXTRACTED_CONFIGS[] = {
|
||||
" }\n",
|
||||
// CONFIGURATION 53
|
||||
"{\n"
|
||||
" \"hosts-databases\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"keatest1\",\n"
|
||||
" \"password\": \"keatest\",\n"
|
||||
" \"type\": \"mysql\",\n"
|
||||
" \"user\": \"keatest\"\n"
|
||||
" },\n"
|
||||
" {\n"
|
||||
" \"name\": \"keatest2\",\n"
|
||||
" \"password\": \"keatest\",\n"
|
||||
" \"type\": \"mysql\",\n"
|
||||
" \"user\": \"keatest\"\n"
|
||||
" }\n"
|
||||
" ],\n"
|
||||
" \"interfaces-config\": {\n"
|
||||
" \"interfaces\": [ \"*\" ],\n"
|
||||
" \"re-detect\": false\n"
|
||||
" },\n"
|
||||
" \"preferred-lifetime\": 3000,\n"
|
||||
" \"rebind-timer\": 2000,\n"
|
||||
" \"renew-timer\": 1000,\n"
|
||||
" \"valid-lifetime\": 4000\n"
|
||||
" }\n",
|
||||
// CONFIGURATION 54
|
||||
"{\n"
|
||||
" \"comment\": \"A DHCPv6 server\",\n"
|
||||
" \"client-classes\": [\n"
|
||||
" {\n"
|
||||
@ -6240,6 +6265,72 @@ const char* UNPARSED_CONFIGS[] = {
|
||||
" }\n",
|
||||
// CONFIGURATION 53
|
||||
"{\n"
|
||||
" \"decline-probation-period\": 86400,\n"
|
||||
" \"dhcp-ddns\": {\n"
|
||||
" \"always-include-fqdn\": false,\n"
|
||||
" \"enable-updates\": false,\n"
|
||||
" \"generated-prefix\": \"myhost\",\n"
|
||||
" \"max-queue-size\": 1024,\n"
|
||||
" \"ncr-format\": \"JSON\",\n"
|
||||
" \"ncr-protocol\": \"UDP\",\n"
|
||||
" \"override-client-update\": false,\n"
|
||||
" \"override-no-update\": false,\n"
|
||||
" \"qualifying-suffix\": \"\",\n"
|
||||
" \"replace-client-name\": \"never\",\n"
|
||||
" \"sender-ip\": \"0.0.0.0\",\n"
|
||||
" \"sender-port\": 0,\n"
|
||||
" \"server-ip\": \"127.0.0.1\",\n"
|
||||
" \"server-port\": 53001\n"
|
||||
" },\n"
|
||||
" \"dhcp4o6-port\": 0,\n"
|
||||
" \"expired-leases-processing\": {\n"
|
||||
" \"flush-reclaimed-timer-wait-time\": 25,\n"
|
||||
" \"hold-reclaimed-time\": 3600,\n"
|
||||
" \"max-reclaim-leases\": 100,\n"
|
||||
" \"max-reclaim-time\": 250,\n"
|
||||
" \"reclaim-timer-wait-time\": 10,\n"
|
||||
" \"unwarned-reclaim-cycles\": 5\n"
|
||||
" },\n"
|
||||
" \"hooks-libraries\": [ ],\n"
|
||||
" \"host-reservation-identifiers\": [ \"hw-address\", \"duid\" ],\n"
|
||||
" \"hosts-databases\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"keatest1\",\n"
|
||||
" \"password\": \"keatest\",\n"
|
||||
" \"type\": \"mysql\",\n"
|
||||
" \"user\": \"keatest\"\n"
|
||||
" },\n"
|
||||
" {\n"
|
||||
" \"name\": \"keatest2\",\n"
|
||||
" \"password\": \"keatest\",\n"
|
||||
" \"type\": \"mysql\",\n"
|
||||
" \"user\": \"keatest\"\n"
|
||||
" }\n"
|
||||
" ],\n"
|
||||
" \"interfaces-config\": {\n"
|
||||
" \"interfaces\": [ \"*\" ],\n"
|
||||
" \"re-detect\": false\n"
|
||||
" },\n"
|
||||
" \"lease-database\": {\n"
|
||||
" \"type\": \"memfile\"\n"
|
||||
" },\n"
|
||||
" \"mac-sources\": [ \"any\" ],\n"
|
||||
" \"option-data\": [ ],\n"
|
||||
" \"option-def\": [ ],\n"
|
||||
" \"relay-supplied-options\": [ \"65\" ],\n"
|
||||
" \"server-id\": {\n"
|
||||
" \"enterprise-id\": 0,\n"
|
||||
" \"htype\": 0,\n"
|
||||
" \"identifier\": \"\",\n"
|
||||
" \"persist\": true,\n"
|
||||
" \"time\": 0,\n"
|
||||
" \"type\": \"LLT\"\n"
|
||||
" },\n"
|
||||
" \"shared-networks\": [ ],\n"
|
||||
" \"subnet6\": [ ]\n"
|
||||
" }\n",
|
||||
// CONFIGURATION 54
|
||||
"{\n"
|
||||
" \"comment\": \"A DHCPv6 server\",\n"
|
||||
" \"client-classes\": [\n"
|
||||
" {\n"
|
||||
@ -6459,7 +6550,7 @@ outputFormatted(const std::string& config) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
@ -125,7 +125,7 @@ outputFormatted(const std::string& config) {
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
@ -156,9 +156,9 @@ extractConfig(const std::string& config) {
|
||||
++extract_count;
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
} // namespace test
|
||||
} // namespace dhcp
|
||||
} // namespace isc
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -89,6 +89,7 @@ libkea_dhcpsrv_la_SOURCES += alloc_engine.cc alloc_engine.h
|
||||
libkea_dhcpsrv_la_SOURCES += alloc_engine_log.cc alloc_engine_log.h
|
||||
libkea_dhcpsrv_la_SOURCES += assignable_network.h
|
||||
libkea_dhcpsrv_la_SOURCES += base_host_data_source.h
|
||||
libkea_dhcpsrv_la_SOURCES += cache_host_data_source.h
|
||||
libkea_dhcpsrv_la_SOURCES += callout_handle_store.h
|
||||
libkea_dhcpsrv_la_SOURCES += cfg_4o6.cc cfg_4o6.h
|
||||
libkea_dhcpsrv_la_SOURCES += cfg_db_access.cc cfg_db_access.h
|
||||
@ -248,6 +249,7 @@ libkea_dhcpsrv_include_HEADERS = \
|
||||
alloc_engine_log.h \
|
||||
assignable_network.h \
|
||||
base_host_data_source.h \
|
||||
cache_host_data_source.h \
|
||||
callout_handle_store.h \
|
||||
cfg_4o6.h \
|
||||
cfg_db_access.h \
|
||||
|
@ -1,4 +1,4 @@
|
||||
// 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
|
||||
@ -14,6 +14,8 @@
|
||||
#include <exceptions/exceptions.h>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
@ -245,7 +247,8 @@ public:
|
||||
/// is identified by HW address, another one by DUID.
|
||||
///
|
||||
/// @param host Pointer to the new @c Host object being added.
|
||||
virtual void add(const HostPtr& host) = 0;
|
||||
/// @return true if addition was successful.
|
||||
virtual bool add(const HostPtr& host) = 0;
|
||||
|
||||
/// @brief Attempts to delete a host by (subnet-id, address)
|
||||
///
|
||||
@ -310,6 +313,9 @@ public:
|
||||
/// @brief HostDataSource pointer
|
||||
typedef boost::shared_ptr<BaseHostDataSource> HostDataSourcePtr;
|
||||
|
||||
/// @brief HostDataSource list
|
||||
typedef std::vector<HostDataSourcePtr> HostDataSourceList;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
64
src/lib/dhcpsrv/cache_host_data_source.h
Normal file
64
src/lib/dhcpsrv/cache_host_data_source.h
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the End User License
|
||||
// Agreement. See COPYING file in the premium/ directory.
|
||||
|
||||
#ifndef CACHE_HOST_DATA_SOURCE_H
|
||||
#define CACHE_HOST_DATA_SOURCE_H
|
||||
|
||||
#include <dhcpsrv/base_host_data_source.h>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
/// @brief Abstract interface extending base simple data source for host
|
||||
/// reservations to host cache.
|
||||
/// Only the insert() method is required to use the cache.
|
||||
class CacheHostDataSource : public virtual BaseHostDataSource {
|
||||
public:
|
||||
|
||||
/// @brief Default destructor implementation.
|
||||
virtual ~CacheHostDataSource() { }
|
||||
|
||||
/// @brief Insert a host into the cache.
|
||||
///
|
||||
/// Does the same than @c add() but with a different purpose.
|
||||
///
|
||||
/// @param host Pointer to the new @c Host object being inserted.
|
||||
/// @param[in,out] overwrite -1 if accepting conflicts, 0 if removing
|
||||
/// conflicting entries, set to the number of removed entries.
|
||||
/// @return true when succeeded.
|
||||
virtual bool insert(const ConstHostPtr& host, int& overwrite) = 0;
|
||||
|
||||
/// @brief Remove a host from the cache.
|
||||
///
|
||||
/// Does the same than @c del, @c del4 or @c del6 but with
|
||||
/// a more uniform interface and a different purpose.
|
||||
///
|
||||
/// @param host Pointer to the existing @c Host object being removed.
|
||||
/// @return true when found and removed.
|
||||
virtual bool remove(const HostPtr& host) = 0;
|
||||
|
||||
/// @brief Flush entries.
|
||||
///
|
||||
/// @param count number of entries to remove, 0 means all.
|
||||
virtual void flush(size_t count) = 0;
|
||||
|
||||
/// @brief Return the number of entries.
|
||||
///
|
||||
/// @return the current number of active entries in the cache.
|
||||
virtual size_t size() const = 0;
|
||||
|
||||
/// @brief Return the maximum number of entries.
|
||||
///
|
||||
/// @return the maximum number of entries, 0 means unbound.
|
||||
virtual size_t capacity() const = 0;
|
||||
};
|
||||
|
||||
/// @brief CacheHostDataSource pointer.
|
||||
typedef boost::shared_ptr<CacheHostDataSource> CacheHostDataSourcePtr;
|
||||
|
||||
} // end of namespace isc::dhcp
|
||||
} // end of namespace isc
|
||||
|
||||
#endif // CACHE_HOST_DATA_SOURCE_H
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2016-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
|
||||
@ -21,21 +21,31 @@ namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
CfgDbAccess::CfgDbAccess()
|
||||
: appended_parameters_(), lease_db_access_("type=memfile"),
|
||||
host_db_access_() {
|
||||
: appended_parameters_(), db_access_(2) {
|
||||
db_access_[LEASE_DB] = "type=memfile";
|
||||
}
|
||||
|
||||
std::string
|
||||
CfgDbAccess::getLeaseDbAccessString() const {
|
||||
return (getAccessString(lease_db_access_));
|
||||
return (getAccessString(db_access_[LEASE_DB]));
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
CfgDbAccess::getHostDbAccessString() const {
|
||||
return (getAccessString(host_db_access_));
|
||||
return (getAccessString(db_access_[HOSTS_DB]));
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
CfgDbAccess::getHostDbAccessStringList() const {
|
||||
std::vector<std::string> ret;
|
||||
for (size_t idx = HOSTS_DB; idx < db_access_.size(); ++idx) {
|
||||
if (!db_access_[idx].empty()) {
|
||||
ret.push_back(getAccessString(db_access_[idx]));
|
||||
}
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void
|
||||
CfgDbAccess::createManagers() const {
|
||||
@ -44,10 +54,15 @@ CfgDbAccess::createManagers() const {
|
||||
LeaseMgrFactory::create(getLeaseDbAccessString());
|
||||
|
||||
// Recreate host data source.
|
||||
HostDataSourceFactory::destroy();
|
||||
if (!host_db_access_.empty()) {
|
||||
HostMgr::create(getHostDbAccessString());
|
||||
HostMgr::create();
|
||||
auto host_db_access_list = getHostDbAccessStringList();
|
||||
for (auto it = host_db_access_list.begin();
|
||||
it != host_db_access_list.end(); ++it) {
|
||||
HostMgr::addSource(*it);
|
||||
}
|
||||
|
||||
// Check for a host cache.
|
||||
HostMgr::checkCacheSource(true);
|
||||
}
|
||||
|
||||
std::string
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2016-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
|
||||
@ -10,6 +10,7 @@
|
||||
#include <cc/cfg_to_element.h>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
@ -21,6 +22,9 @@ namespace dhcp {
|
||||
/// passed to the @ref isc::dhcp::LeaseMgrFactory::create function.
|
||||
class CfgDbAccess {
|
||||
public:
|
||||
/// @brief Specifies the database types
|
||||
static const size_t LEASE_DB = 0;
|
||||
static const size_t HOSTS_DB = 1;
|
||||
|
||||
/// @brief Constructor.
|
||||
CfgDbAccess();
|
||||
@ -44,7 +48,7 @@ public:
|
||||
///
|
||||
/// @param lease_db_access New lease database access string.
|
||||
void setLeaseDbAccessString(const std::string& lease_db_access) {
|
||||
lease_db_access_ = lease_db_access;
|
||||
db_access_[LEASE_DB] = lease_db_access;
|
||||
}
|
||||
|
||||
/// @brief Retrieves host database access string.
|
||||
@ -57,10 +61,23 @@ public:
|
||||
///
|
||||
/// @param host_db_access New host database access string.
|
||||
void setHostDbAccessString(const std::string& host_db_access) {
|
||||
host_db_access_ = host_db_access;
|
||||
db_access_[HOSTS_DB] = host_db_access;
|
||||
}
|
||||
|
||||
/// @brief Creates instance of lease manager and host data source
|
||||
/// @brief Retrieves host database access string.
|
||||
///
|
||||
/// @return Database access strings with additional parameters
|
||||
/// specified with @ref CfgDbAccess::setAppendedParameters
|
||||
std::vector<std::string> getHostDbAccessStringList() const;
|
||||
|
||||
/// @brief Pushes host database access string.
|
||||
///
|
||||
/// @param db_access New host database access string.
|
||||
void pushHostDbAccessString(const std::string& db_access) {
|
||||
db_access_.push_back(db_access);
|
||||
}
|
||||
|
||||
/// @brief Creates instance of lease manager and host data sources
|
||||
/// according to the configuration specified.
|
||||
void createManagers() const;
|
||||
|
||||
@ -82,11 +99,8 @@ protected:
|
||||
/// strings.
|
||||
std::string appended_parameters_;
|
||||
|
||||
/// @brief Holds lease database access string.
|
||||
std::string lease_db_access_;
|
||||
|
||||
/// @brief Holds host database access string.
|
||||
std::string host_db_access_;
|
||||
/// @brief Holds database access strings.
|
||||
std::vector<std::string> db_access_;
|
||||
|
||||
};
|
||||
|
||||
@ -107,7 +121,7 @@ struct CfgLeaseDbAccess : public CfgDbAccess, public isc::data::CfgToElement {
|
||||
///
|
||||
/// @result a pointer to a configuration
|
||||
virtual isc::data::ElementPtr toElement() const {
|
||||
return (CfgDbAccess::toElementDbAccessString(lease_db_access_));
|
||||
return (CfgDbAccess::toElementDbAccessString(db_access_[LEASE_DB]));
|
||||
}
|
||||
};
|
||||
|
||||
@ -121,7 +135,15 @@ struct CfgHostDbAccess : public CfgDbAccess, public isc::data::CfgToElement {
|
||||
///
|
||||
/// @result a pointer to a configuration
|
||||
virtual isc::data::ElementPtr toElement() const {
|
||||
return (CfgDbAccess::toElementDbAccessString(host_db_access_));
|
||||
isc::data::ElementPtr result = isc::data::Element::createList();
|
||||
for (size_t idx = HOSTS_DB; idx < db_access_.size(); ++idx) {
|
||||
isc::data::ElementPtr entry =
|
||||
CfgDbAccess::toElementDbAccessString(db_access_[idx]);
|
||||
if (entry->size() > 0) {
|
||||
result->add(entry);
|
||||
}
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// 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
|
||||
@ -549,7 +549,7 @@ CfgHosts::getHostInternal(const SubnetID& subnet_id, const bool subnet6,
|
||||
return (host);
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
CfgHosts::add(const HostPtr& host) {
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_ADD_HOST)
|
||||
.arg(host ? host->toText() : "(no-host)");
|
||||
@ -569,6 +569,8 @@ CfgHosts::add(const HostPtr& host) {
|
||||
add4(host);
|
||||
|
||||
add6(host);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1,4 +1,4 @@
|
||||
// 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
|
||||
@ -318,9 +318,10 @@ public:
|
||||
///
|
||||
/// @param host Pointer to the new @c Host object being added.
|
||||
///
|
||||
/// @return always return true as additions are successful or throw.
|
||||
/// @throw DuplicateHost If a host for a particular HW address or DUID
|
||||
/// has already been added to the IPv4 or IPv6 subnet.
|
||||
virtual void add(const HostPtr& host);
|
||||
virtual bool add(const HostPtr& host);
|
||||
|
||||
/// @brief Attempts to delete a host by address.
|
||||
///
|
||||
|
@ -1782,11 +1782,13 @@ CqlHostDataSource::~CqlHostDataSource() {
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
CqlHostDataSource::add(const HostPtr& host) {
|
||||
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_HOST_ADD);
|
||||
|
||||
impl_->add(host);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
ConstHostCollection
|
||||
|
@ -98,7 +98,8 @@ public:
|
||||
/// Host, where one instance is identified by different identifier types.
|
||||
///
|
||||
/// @param host pointer to the new @ref Host being added.
|
||||
virtual void add(const HostPtr& host) override;
|
||||
/// @return true as addition is successful or throws.
|
||||
virtual bool add(const HostPtr& host) override;
|
||||
|
||||
/// @brief Retrieves a single @ref Host connected to an IPv4 subnet.
|
||||
///
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2012-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2012-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
|
||||
|
@ -1,4 +1,4 @@
|
||||
// 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
|
||||
@ -92,7 +92,8 @@ Host::Host(const uint8_t* identifier, const size_t identifier_len,
|
||||
dhcp6_client_classes_(dhcp6_client_classes),
|
||||
next_server_(asiolink::IOAddress::IPV4_ZERO_ADDRESS()),
|
||||
server_host_name_(server_host_name), boot_file_name_(boot_file_name),
|
||||
host_id_(0), cfg_option4_(new CfgOption()), cfg_option6_(new CfgOption()) {
|
||||
host_id_(0), cfg_option4_(new CfgOption()),
|
||||
cfg_option6_(new CfgOption()), negative_(false) {
|
||||
|
||||
// Initialize host identifier.
|
||||
setIdentifier(identifier, identifier_len, identifier_type);
|
||||
@ -125,7 +126,8 @@ Host::Host(const std::string& identifier, const std::string& identifier_name,
|
||||
dhcp6_client_classes_(dhcp6_client_classes),
|
||||
next_server_(asiolink::IOAddress::IPV4_ZERO_ADDRESS()),
|
||||
server_host_name_(server_host_name), boot_file_name_(boot_file_name),
|
||||
host_id_(0), cfg_option4_(new CfgOption()), cfg_option6_(new CfgOption()) {
|
||||
host_id_(0), cfg_option4_(new CfgOption()),
|
||||
cfg_option6_(new CfgOption()), negative_(false) {
|
||||
|
||||
// Initialize host identifier.
|
||||
setIdentifier(identifier, identifier_name);
|
||||
@ -589,6 +591,11 @@ Host::toText() const {
|
||||
<< "=" << *cclass;
|
||||
}
|
||||
|
||||
// Add negative cached.
|
||||
if (negative_) {
|
||||
s << " negative cached";
|
||||
}
|
||||
|
||||
return (s.str());
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// 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
|
||||
@ -546,6 +546,18 @@ public:
|
||||
return (host_id_);
|
||||
}
|
||||
|
||||
/// @brief Sets the negative cached flag.
|
||||
///
|
||||
/// @param negative New valie for negative cache flag.
|
||||
void setNegative(bool negative) {
|
||||
negative_ = negative;
|
||||
}
|
||||
|
||||
/// @brief Return the negative cache flag value.
|
||||
bool getNegative() const {
|
||||
return (negative_);
|
||||
}
|
||||
|
||||
/// @brief Unparses (converts to Element representation) IPv4 host
|
||||
///
|
||||
/// @return Element representation of the host
|
||||
@ -604,6 +616,9 @@ private:
|
||||
CfgOptionPtr cfg_option4_;
|
||||
/// @brief Pointer to the DHCPv6 option data configuration for this host.
|
||||
CfgOptionPtr cfg_option6_;
|
||||
|
||||
/// @brief Negative cached flag.
|
||||
bool negative_;
|
||||
};
|
||||
|
||||
/// @brief Pointer to the @c Host object.
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2015-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
|
||||
@ -38,14 +38,11 @@ using namespace std;
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
HostDataSourcePtr&
|
||||
HostDataSourceFactory::getHostDataSourcePtr() {
|
||||
static HostDataSourcePtr hostDataSourcePtr;
|
||||
return (hostDataSourcePtr);
|
||||
}
|
||||
map<string, HostDataSourceFactory::Factory> HostDataSourceFactory::map_;
|
||||
|
||||
void
|
||||
HostDataSourceFactory::create(const std::string& dbaccess) {
|
||||
HostDataSourceFactory::add(HostDataSourceList& sources,
|
||||
const string& dbaccess) {
|
||||
// Parse the access string and create a redacted string for logging.
|
||||
DatabaseConnection::ParameterMap parameters =
|
||||
DatabaseConnection::parse(dbaccess);
|
||||
@ -57,62 +54,146 @@ HostDataSourceFactory::create(const std::string& dbaccess) {
|
||||
"contain the 'type' keyword");
|
||||
}
|
||||
|
||||
std::string db_type = it->second;
|
||||
string db_type = it->second;
|
||||
auto index = map_.find(db_type);
|
||||
|
||||
#ifdef HAVE_MYSQL
|
||||
if (db_type == "mysql") {
|
||||
LOG_INFO(dhcpsrv_logger, DHCPSRV_MYSQL_HOST_DB)
|
||||
.arg(DatabaseConnection::redactedAccessString(parameters));
|
||||
getHostDataSourcePtr().reset(new MySqlHostDataSource(parameters));
|
||||
return;
|
||||
// No match?
|
||||
if (index == map_.end()) {
|
||||
isc_throw(InvalidType, "Hosts database access parameter 'type': " <<
|
||||
db_type << " is invalid");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PGSQL
|
||||
if (db_type == "postgresql") {
|
||||
LOG_INFO(dhcpsrv_logger, DHCPSRV_PGSQL_HOST_DB)
|
||||
.arg(DatabaseConnection::redactedAccessString(parameters));
|
||||
getHostDataSourcePtr().reset(new PgSqlHostDataSource(parameters));
|
||||
return;
|
||||
// Call the factory and push the pointer on sources.
|
||||
sources.push_back(boost::shared_ptr<BaseHostDataSource>(index->second(parameters)));
|
||||
|
||||
// Check the factory did not return NULL.
|
||||
if (!sources.back()) {
|
||||
sources.pop_back();
|
||||
isc_throw(Unexpected, "Hosts database " << db_type <<
|
||||
" factory returned NULL");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CQL
|
||||
if (db_type == "cql") {
|
||||
LOG_INFO(dhcpsrv_logger, DHCPSRV_CQL_HOST_DB)
|
||||
.arg(DatabaseConnection::redactedAccessString(parameters));
|
||||
getHostDataSourcePtr().reset(new CqlHostDataSource(parameters));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Get here on no match.
|
||||
isc_throw(InvalidType, "Hosts database access parameter 'type': " <<
|
||||
db_type << " is invalid");
|
||||
}
|
||||
|
||||
void
|
||||
HostDataSourceFactory::destroy() {
|
||||
// Destroy current host data source instance. This is a no-op if no host
|
||||
// data source is available.
|
||||
if (getHostDataSourcePtr()) {
|
||||
bool
|
||||
HostDataSourceFactory::del(HostDataSourceList& sources,
|
||||
const string& db_type) {
|
||||
for (auto it = sources.begin(); it != sources.end(); ++it) {
|
||||
if ((*it)->getType() != db_type) {
|
||||
continue;
|
||||
}
|
||||
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, HOSTS_CFG_CLOSE_HOST_DATA_SOURCE)
|
||||
.arg(getHostDataSourcePtr()->getType());
|
||||
.arg(db_type);
|
||||
sources.erase(it);
|
||||
return (true);
|
||||
}
|
||||
getHostDataSourcePtr().reset();
|
||||
return (false);
|
||||
}
|
||||
|
||||
#if 0
|
||||
BaseHostDataSource&
|
||||
HostDataSourceFactory::instance() {
|
||||
BaseHostDataSource* hdsptr = getHostDataSourcePtr().get();
|
||||
if (hdsptr == NULL) {
|
||||
isc_throw(NoHostDataSourceManager,
|
||||
"no current host data source instance is available");
|
||||
bool
|
||||
HostDataSourceFactory::registerFactory(const string& db_type,
|
||||
const Factory& factory) {
|
||||
if (map_.count(db_type)) {
|
||||
return (false);
|
||||
}
|
||||
map_.insert(pair<string, Factory>(db_type, factory));
|
||||
return (true);
|
||||
}
|
||||
|
||||
bool
|
||||
HostDataSourceFactory::deregisterFactory(const string& db_type) {
|
||||
auto index = map_.find(db_type);
|
||||
if (index != map_.end()) {
|
||||
map_.erase(index);
|
||||
return (true);
|
||||
} else {
|
||||
return (false);
|
||||
}
|
||||
return (*hdsptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace dhcp
|
||||
} // namespace isc
|
||||
|
||||
//
|
||||
// Register database backends
|
||||
//
|
||||
|
||||
using namespace isc::dhcp;
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef HAVE_MYSQL
|
||||
struct MySqlHostDataSourceInit {
|
||||
// Constructor registers
|
||||
MySqlHostDataSourceInit() {
|
||||
HostDataSourceFactory::registerFactory("mysql", factory);
|
||||
}
|
||||
|
||||
// Destructor deregisters
|
||||
~MySqlHostDataSourceInit() {
|
||||
HostDataSourceFactory::deregisterFactory("mysql");
|
||||
}
|
||||
|
||||
// Factory class method
|
||||
static BaseHostDataSource*
|
||||
factory(const DatabaseConnection::ParameterMap& parameters) {
|
||||
LOG_INFO(dhcpsrv_logger, DHCPSRV_MYSQL_HOST_DB)
|
||||
.arg(DatabaseConnection::redactedAccessString(parameters));
|
||||
return (new MySqlHostDataSource(parameters));
|
||||
}
|
||||
};
|
||||
|
||||
// Database backend will be registered at object initialization
|
||||
MySqlHostDataSourceInit mysql_init_;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PGSQL
|
||||
struct PgSqlHostDataSourceInit {
|
||||
// Constructor registers
|
||||
PgSqlHostDataSourceInit() {
|
||||
HostDataSourceFactory::registerFactory("postgresql", factory);
|
||||
}
|
||||
|
||||
// Destructor deregisters
|
||||
~PgSqlHostDataSourceInit() {
|
||||
HostDataSourceFactory::deregisterFactory("postgresql");
|
||||
}
|
||||
|
||||
// Factory class method
|
||||
static BaseHostDataSource*
|
||||
factory(const DatabaseConnection::ParameterMap& parameters) {
|
||||
LOG_INFO(dhcpsrv_logger, DHCPSRV_PGSQL_HOST_DB)
|
||||
.arg(DatabaseConnection::redactedAccessString(parameters));
|
||||
return (new PgSqlHostDataSource(parameters));
|
||||
}
|
||||
};
|
||||
|
||||
// Database backend will be registered at object initialization
|
||||
PgSqlHostDataSourceInit pgsql_init_;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CQL
|
||||
struct CqlHostDataSourceInit {
|
||||
// Constructor registers
|
||||
CqlHostDataSourceInit() {
|
||||
HostDataSourceFactory::registerFactory("cql", factory);
|
||||
}
|
||||
|
||||
// Destructor deregisters
|
||||
~CqlHostDataSourceInit() {
|
||||
HostDataSourceFactory::deregisterFactory("cql");
|
||||
}
|
||||
|
||||
// Factory class method
|
||||
static BaseHostDataSource*
|
||||
factory(const DatabaseConnection::ParameterMap& parameters) {
|
||||
LOG_INFO(dhcpsrv_logger, DHCPSRV_CQL_HOST_DB)
|
||||
.arg(DatabaseConnection::redactedAccessString(parameters));
|
||||
return (new CqlHostDataSource(parameters));
|
||||
}
|
||||
};
|
||||
|
||||
// Database backend will be registered at object initialization
|
||||
CqlHostDataSourceInit cql_init_;
|
||||
#endif
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2015-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
|
||||
@ -11,8 +11,10 @@
|
||||
#include <dhcpsrv/database_connection.h>
|
||||
#include <exceptions/exceptions.h>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/function.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
@ -38,21 +40,18 @@ public:
|
||||
|
||||
class HostDataSourceFactory {
|
||||
public:
|
||||
/// @brief Create an instance of a host data source.
|
||||
/// @brief Create and add an instance of a host data source.
|
||||
///
|
||||
/// Each database backend has its own host data source type. This static
|
||||
/// method sets the "current" host data source to be an object of the
|
||||
/// appropriate type. The actual host data source is returned by the
|
||||
/// "instance" method.
|
||||
///
|
||||
/// @note When called, the current host data source is <b>always</b> destroyed
|
||||
/// and a new one created - even if the parameters are the same.
|
||||
/// method adds an object of the appropriate type to a list of
|
||||
/// host data sources.
|
||||
///
|
||||
/// dbaccess is a generic way of passing parameters. Parameters are passed
|
||||
/// in the "name=value" format, separated by spaces. The data MUST include
|
||||
/// a keyword/value pair of the form "type=dbtype" giving the database
|
||||
/// type, e.q. "mysql" or "sqlite3".
|
||||
///
|
||||
/// @param sources host data source list.
|
||||
/// @param dbaccess Database access parameters. These are in the form of
|
||||
/// "keyword=value" pairs, separated by spaces. They are backend-
|
||||
/// -end specific, although must include the "type" keyword which
|
||||
@ -62,21 +61,47 @@ public:
|
||||
/// keyword.
|
||||
/// @throw isc::dhcp::InvalidType The "type" keyword in dbaccess does not
|
||||
/// identify a supported backend.
|
||||
static void create(const std::string& dbaccess);
|
||||
static void add(HostDataSourceList& sources, const std::string& dbaccess);
|
||||
|
||||
/// @brief Destroy host data source
|
||||
/// @brief Delete a host data source.
|
||||
///
|
||||
/// Destroys the current host data source object. This should have the effect
|
||||
/// of closing the database connection. The method is a no-op if no
|
||||
/// host data source is available.
|
||||
static void destroy();
|
||||
/// Delete the first instance of a host data source of the given type.
|
||||
/// This should have the effect of closing the database connection.
|
||||
///
|
||||
/// @param sources host data source list.
|
||||
/// @param db_type database backend type.
|
||||
/// @return true when found and removed, false when not found.
|
||||
static bool del(HostDataSourceList& sources, const std::string& db_type);
|
||||
|
||||
/// @brief Hold pointer to host data source instance
|
||||
/// @brief Type of host data source factory
|
||||
///
|
||||
/// Holds a pointer to the singleton host data source. The singleton
|
||||
/// is encapsulated in this method to avoid a "static initialization
|
||||
/// fiasco" if defined in an external static variable.
|
||||
static HostDataSourcePtr& getHostDataSourcePtr();
|
||||
/// A factory takes a parameter map and returns a pointer to a host
|
||||
/// data source. In case of failure it must throw and not return NULL.
|
||||
typedef boost::function<BaseHostDataSource*(const DatabaseConnection::ParameterMap&)> Factory;
|
||||
|
||||
/// @brief Register a host data source factory
|
||||
///
|
||||
/// Associate the factory to a database type in the map.
|
||||
///
|
||||
/// @param db_type database type
|
||||
/// @param factory host data source factory
|
||||
/// @return true if the factory was successfully added to the map, false
|
||||
/// if it already exists.
|
||||
static bool registerFactory(const std::string& db_type,
|
||||
const Factory& factory);
|
||||
|
||||
/// @brief Deregister a host data source factory
|
||||
///
|
||||
/// Disassociate the factory to a database type in the map.
|
||||
///
|
||||
/// @param db_type database type
|
||||
/// @return true if the factory was successfully removed from the map,
|
||||
/// false if it was not found.
|
||||
static bool deregisterFactory(const std::string& db_type);
|
||||
|
||||
private:
|
||||
/// @brief Factory map
|
||||
static std::map<std::string, Factory> map_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// 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
|
||||
@ -37,24 +37,53 @@ HostMgr::getHostMgrPtr() {
|
||||
}
|
||||
|
||||
void
|
||||
HostMgr::create(const std::string& access) {
|
||||
HostMgr::create() {
|
||||
getHostMgrPtr().reset(new HostMgr());
|
||||
}
|
||||
|
||||
if (!access.empty()) {
|
||||
// If the user specified parameters, let's pass them to the create
|
||||
// method. It will destroy any prior instances and will create
|
||||
// the new one.
|
||||
HostDataSourceFactory::create(access);
|
||||
} else {
|
||||
// Ok, no parameters were specified. We should destroy the existing
|
||||
// instance.
|
||||
HostDataSourceFactory::destroy();
|
||||
void
|
||||
HostMgr::addSource(const std::string& access) {
|
||||
HostDataSourceFactory::add(getHostMgrPtr()->alternate_sources_, access);
|
||||
}
|
||||
|
||||
bool
|
||||
HostMgr::delSource(const std::string& db_type) {
|
||||
return (HostDataSourceFactory::del(getHostMgrPtr()->alternate_sources_, db_type));
|
||||
}
|
||||
|
||||
void
|
||||
HostMgr::delAllSources() {
|
||||
getHostMgrPtr()->alternate_sources_.clear();
|
||||
}
|
||||
|
||||
HostDataSourcePtr
|
||||
HostMgr::getHostDataSource() const {
|
||||
if (alternate_sources_.empty()) {
|
||||
return (HostDataSourcePtr());
|
||||
}
|
||||
return (alternate_sources_[0]);
|
||||
}
|
||||
|
||||
// Now store the host data source pointer. It may be NULL. That's ok as
|
||||
// NULL value indicates that there's no host data source configured.
|
||||
getHostMgrPtr()->alternate_source_ =
|
||||
HostDataSourceFactory::getHostDataSourcePtr();
|
||||
bool
|
||||
HostMgr::checkCacheSource(bool logging) {
|
||||
if (getHostMgrPtr()->cache_ptr_) {
|
||||
return (true);
|
||||
}
|
||||
HostDataSourceList& sources = getHostMgrPtr()->alternate_sources_;
|
||||
if (sources.empty()) {
|
||||
return (false);
|
||||
}
|
||||
CacheHostDataSourcePtr cache_ptr =
|
||||
boost::dynamic_pointer_cast<CacheHostDataSource>(sources[0]);
|
||||
if (cache_ptr) {
|
||||
getHostMgrPtr()->cache_ptr_ = cache_ptr;
|
||||
if (logging) {
|
||||
LOG_INFO(hosts_logger, HOSTS_CFG_CACHE_HOST_DATA_SOURCE)
|
||||
.arg(cache_ptr->getType());
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
HostMgr&
|
||||
@ -69,8 +98,9 @@ HostMgr::instance() {
|
||||
ConstHostCollection
|
||||
HostMgr::getAll(const HWAddrPtr& hwaddr, const DuidPtr& duid) const {
|
||||
ConstHostCollection hosts = getCfgHosts()->getAll(hwaddr, duid);
|
||||
if (alternate_source_) {
|
||||
ConstHostCollection hosts_plus = alternate_source_->getAll(hwaddr, duid);
|
||||
for (auto it = alternate_sources_.begin();
|
||||
it != alternate_sources_.end(); ++it) {
|
||||
ConstHostCollection hosts_plus = (*it)->getAll(hwaddr, duid);
|
||||
hosts.insert(hosts.end(), hosts_plus.begin(), hosts_plus.end());
|
||||
}
|
||||
return (hosts);
|
||||
@ -83,10 +113,10 @@ HostMgr::getAll(const Host::IdentifierType& identifier_type,
|
||||
ConstHostCollection hosts = getCfgHosts()->getAll(identifier_type,
|
||||
identifier_begin,
|
||||
identifier_len);
|
||||
if (alternate_source_) {
|
||||
for (auto it = alternate_sources_.begin();
|
||||
it != alternate_sources_.end(); ++it) {
|
||||
ConstHostCollection hosts_plus =
|
||||
alternate_source_->getAll(identifier_type, identifier_begin,
|
||||
identifier_len);
|
||||
(*it)->getAll(identifier_type, identifier_begin, identifier_len);
|
||||
hosts.insert(hosts.end(), hosts_plus.begin(), hosts_plus.end());
|
||||
}
|
||||
return (hosts);
|
||||
@ -96,8 +126,9 @@ HostMgr::getAll(const Host::IdentifierType& identifier_type,
|
||||
ConstHostCollection
|
||||
HostMgr::getAll4(const IOAddress& address) const {
|
||||
ConstHostCollection hosts = getCfgHosts()->getAll4(address);
|
||||
if (alternate_source_) {
|
||||
ConstHostCollection hosts_plus = alternate_source_->getAll4(address);
|
||||
for (auto it = alternate_sources_.begin();
|
||||
it != alternate_sources_.end(); ++it) {
|
||||
ConstHostCollection hosts_plus = (*it)->getAll4(address);
|
||||
hosts.insert(hosts.end(), hosts_plus.begin(), hosts_plus.end());
|
||||
}
|
||||
return (hosts);
|
||||
@ -107,18 +138,78 @@ ConstHostPtr
|
||||
HostMgr::get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr,
|
||||
const DuidPtr& duid) const {
|
||||
ConstHostPtr host = getCfgHosts()->get4(subnet_id, hwaddr, duid);
|
||||
if (!host && alternate_source_) {
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
|
||||
HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_HWADDR_DUID)
|
||||
.arg(subnet_id)
|
||||
.arg(hwaddr ? hwaddr->toText() : "(no-hwaddr)")
|
||||
.arg(duid ? duid->toText() : "(duid)");
|
||||
if (host || alternate_sources_.empty()) {
|
||||
return (host);
|
||||
}
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
|
||||
HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_HWADDR_DUID)
|
||||
.arg(subnet_id)
|
||||
.arg(hwaddr ? hwaddr->toText() : "(no-hwaddr)")
|
||||
.arg(duid ? duid->toText() : "(duid)");
|
||||
for (auto it = alternate_sources_.begin();
|
||||
!host && it != alternate_sources_.end(); ++it) {
|
||||
if (duid) {
|
||||
host = alternate_source_->get4(subnet_id, HWAddrPtr(), duid);
|
||||
host = (*it)->get4(subnet_id, HWAddrPtr(), duid);
|
||||
}
|
||||
if (!host && hwaddr) {
|
||||
host = alternate_source_->get4(subnet_id, hwaddr, DuidPtr());
|
||||
host = (*it)->get4(subnet_id, hwaddr, DuidPtr());
|
||||
}
|
||||
if (host && cache_ptr_ && (it != alternate_sources_.begin())) {
|
||||
cache(host);
|
||||
}
|
||||
}
|
||||
if (host && host->getNegative()) {
|
||||
return (ConstHostPtr());
|
||||
}
|
||||
return (host);
|
||||
}
|
||||
|
||||
ConstHostPtr
|
||||
HostMgr::get4Any(const SubnetID& subnet_id,
|
||||
const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin,
|
||||
const size_t identifier_len) const {
|
||||
ConstHostPtr host = getCfgHosts()->get4(subnet_id, identifier_type,
|
||||
identifier_begin, identifier_len);
|
||||
if (host || alternate_sources_.empty()) {
|
||||
return (host);
|
||||
}
|
||||
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
|
||||
HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_IDENTIFIER)
|
||||
.arg(subnet_id)
|
||||
.arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
|
||||
identifier_len));
|
||||
|
||||
for (auto it = alternate_sources_.begin();
|
||||
it != alternate_sources_.end(); ++it) {
|
||||
host = (*it)->get4(subnet_id, identifier_type,
|
||||
identifier_begin, identifier_len);
|
||||
|
||||
if (host) {
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
|
||||
HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_IDENTIFIER_HOST)
|
||||
.arg(subnet_id)
|
||||
.arg(Host::getIdentifierAsText(identifier_type,
|
||||
identifier_begin,
|
||||
identifier_len))
|
||||
.arg((*it)->getType())
|
||||
.arg(host->toText());
|
||||
|
||||
if (cache_ptr_ && (it != alternate_sources_.begin())) {
|
||||
cache(host);
|
||||
}
|
||||
return (host);
|
||||
}
|
||||
}
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
|
||||
HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_IDENTIFIER_NULL)
|
||||
.arg(subnet_id)
|
||||
.arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
|
||||
identifier_len));
|
||||
if (negative_caching_) {
|
||||
cacheNegative(subnet_id, SubnetID(0),
|
||||
identifier_type, identifier_begin, identifier_len);
|
||||
}
|
||||
return (host);
|
||||
}
|
||||
@ -128,49 +219,34 @@ HostMgr::get4(const SubnetID& subnet_id,
|
||||
const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin,
|
||||
const size_t identifier_len) const {
|
||||
ConstHostPtr host = getCfgHosts()->get4(subnet_id, identifier_type,
|
||||
identifier_begin, identifier_len);
|
||||
if (!host && alternate_source_) {
|
||||
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
|
||||
HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_IDENTIFIER)
|
||||
.arg(subnet_id)
|
||||
.arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
|
||||
identifier_len));
|
||||
|
||||
host = alternate_source_->get4(subnet_id, identifier_type,
|
||||
identifier_begin, identifier_len);
|
||||
|
||||
if (host) {
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
|
||||
HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_IDENTIFIER_HOST)
|
||||
.arg(subnet_id)
|
||||
.arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
|
||||
identifier_len))
|
||||
.arg(host->toText());
|
||||
|
||||
} else {
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
|
||||
HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_IDENTIFIER_NULL)
|
||||
.arg(subnet_id)
|
||||
.arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
|
||||
identifier_len));
|
||||
}
|
||||
ConstHostPtr host = get4Any(subnet_id, identifier_type,
|
||||
identifier_begin, identifier_len);
|
||||
if (host && host->getNegative()) {
|
||||
return (ConstHostPtr());
|
||||
}
|
||||
|
||||
return (host);
|
||||
}
|
||||
|
||||
|
||||
ConstHostPtr
|
||||
HostMgr::get4(const SubnetID& subnet_id,
|
||||
const asiolink::IOAddress& address) const {
|
||||
ConstHostPtr host = getCfgHosts()->get4(subnet_id, address);
|
||||
if (!host && alternate_source_) {
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
|
||||
HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_ADDRESS4)
|
||||
.arg(subnet_id)
|
||||
.arg(address.toText());
|
||||
host = alternate_source_->get4(subnet_id, address);
|
||||
if (host || alternate_sources_.empty()) {
|
||||
return (host);
|
||||
}
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
|
||||
HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_ADDRESS4)
|
||||
.arg(subnet_id)
|
||||
.arg(address.toText());
|
||||
for (auto it = alternate_sources_.begin();
|
||||
!host && it != alternate_sources_.end(); ++it) {
|
||||
host = (*it)->get4(subnet_id, address);
|
||||
if (host && cache_ptr_ && (it != alternate_sources_.begin())) {
|
||||
cache(host);
|
||||
}
|
||||
}
|
||||
if (host && host->getNegative()) {
|
||||
return (ConstHostPtr());
|
||||
}
|
||||
return (host);
|
||||
}
|
||||
@ -180,18 +256,29 @@ ConstHostPtr
|
||||
HostMgr::get6(const SubnetID& subnet_id, const DuidPtr& duid,
|
||||
const HWAddrPtr& hwaddr) const {
|
||||
ConstHostPtr host = getCfgHosts()->get6(subnet_id, duid, hwaddr);
|
||||
if (!host && alternate_source_) {
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
|
||||
HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_DUID_HWADDR)
|
||||
.arg(subnet_id)
|
||||
.arg(duid ? duid->toText() : "(duid)")
|
||||
.arg(hwaddr ? hwaddr->toText() : "(no-hwaddr)");
|
||||
if (host || alternate_sources_.empty()) {
|
||||
return (host);
|
||||
}
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
|
||||
HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_DUID_HWADDR)
|
||||
.arg(subnet_id)
|
||||
.arg(duid ? duid->toText() : "(duid)")
|
||||
.arg(hwaddr ? hwaddr->toText() : "(no-hwaddr)");
|
||||
|
||||
for (auto it = alternate_sources_.begin();
|
||||
!host && it != alternate_sources_.end(); ++it) {
|
||||
if (duid) {
|
||||
host = alternate_source_->get6(subnet_id, duid, HWAddrPtr());
|
||||
host = (*it)->get6(subnet_id, duid, HWAddrPtr());
|
||||
}
|
||||
if (!host && hwaddr) {
|
||||
host = alternate_source_->get6(subnet_id, DuidPtr(), hwaddr);
|
||||
host = (*it)->get6(subnet_id, DuidPtr(), hwaddr);
|
||||
}
|
||||
if (host && cache_ptr_ && (it != alternate_sources_.begin())) {
|
||||
cache(host);
|
||||
}
|
||||
}
|
||||
if (host && host->getNegative()) {
|
||||
return (ConstHostPtr());
|
||||
}
|
||||
return (host);
|
||||
}
|
||||
@ -199,13 +286,77 @@ HostMgr::get6(const SubnetID& subnet_id, const DuidPtr& duid,
|
||||
ConstHostPtr
|
||||
HostMgr::get6(const IOAddress& prefix, const uint8_t prefix_len) const {
|
||||
ConstHostPtr host = getCfgHosts()->get6(prefix, prefix_len);
|
||||
if (!host && alternate_source_) {
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
|
||||
HOSTS_MGR_ALTERNATE_GET6_PREFIX)
|
||||
.arg(prefix.toText())
|
||||
.arg(static_cast<int>(prefix_len));
|
||||
host = alternate_source_->get6(prefix, prefix_len);
|
||||
if (host || alternate_sources_.empty()) {
|
||||
return (host);
|
||||
}
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
|
||||
HOSTS_MGR_ALTERNATE_GET6_PREFIX)
|
||||
.arg(prefix.toText())
|
||||
.arg(static_cast<int>(prefix_len));
|
||||
for (auto it = alternate_sources_.begin();
|
||||
!host && it != alternate_sources_.end(); ++it) {
|
||||
host = (*it)->get6(prefix, prefix_len);
|
||||
if (host && cache_ptr_ && (it != alternate_sources_.begin())) {
|
||||
cache(host);
|
||||
}
|
||||
}
|
||||
if (host && host->getNegative()) {
|
||||
return (ConstHostPtr());
|
||||
}
|
||||
return (host);
|
||||
}
|
||||
|
||||
ConstHostPtr
|
||||
HostMgr::get6Any(const SubnetID& subnet_id,
|
||||
const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin,
|
||||
const size_t identifier_len) const {
|
||||
ConstHostPtr host = getCfgHosts()->get6(subnet_id, identifier_type,
|
||||
identifier_begin, identifier_len);
|
||||
if (host || alternate_sources_.empty()) {
|
||||
return (host);
|
||||
}
|
||||
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
|
||||
HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_IDENTIFIER)
|
||||
.arg(subnet_id)
|
||||
.arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
|
||||
identifier_len));
|
||||
|
||||
for (auto it = alternate_sources_.begin();
|
||||
it != alternate_sources_.end(); ++it) {
|
||||
|
||||
host = (*it)->get6(subnet_id, identifier_type,
|
||||
identifier_begin, identifier_len);
|
||||
|
||||
if (host) {
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
|
||||
HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_IDENTIFIER_HOST)
|
||||
.arg(subnet_id)
|
||||
.arg(Host::getIdentifierAsText(identifier_type,
|
||||
identifier_begin,
|
||||
identifier_len))
|
||||
.arg((*it)->getType())
|
||||
.arg(host->toText());
|
||||
|
||||
if (cache_ptr_ && (it != alternate_sources_.begin())) {
|
||||
cache(host);
|
||||
}
|
||||
return (host);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
|
||||
HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_IDENTIFIER_NULL)
|
||||
.arg(subnet_id)
|
||||
.arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
|
||||
identifier_len));
|
||||
|
||||
if (negative_caching_) {
|
||||
cacheNegative(SubnetID(0), subnet_id,
|
||||
identifier_type, identifier_begin, identifier_len);
|
||||
}
|
||||
|
||||
return (host);
|
||||
}
|
||||
|
||||
@ -214,36 +365,10 @@ HostMgr::get6(const SubnetID& subnet_id,
|
||||
const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin,
|
||||
const size_t identifier_len) const {
|
||||
ConstHostPtr host = getCfgHosts()->get6(subnet_id, identifier_type,
|
||||
identifier_begin, identifier_len);
|
||||
if (!host && alternate_source_) {
|
||||
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
|
||||
HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_IDENTIFIER)
|
||||
.arg(subnet_id)
|
||||
.arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
|
||||
identifier_len));
|
||||
|
||||
|
||||
host = alternate_source_->get6(subnet_id, identifier_type,
|
||||
identifier_begin, identifier_len);
|
||||
|
||||
if (host) {
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
|
||||
HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_IDENTIFIER_HOST)
|
||||
.arg(subnet_id)
|
||||
.arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
|
||||
identifier_len))
|
||||
.arg(host->toText());
|
||||
|
||||
} else {
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
|
||||
HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_IDENTIFIER_NULL)
|
||||
.arg(subnet_id)
|
||||
.arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
|
||||
identifier_len));
|
||||
}
|
||||
|
||||
ConstHostPtr host = get6Any(subnet_id, identifier_type,
|
||||
identifier_begin, identifier_len);
|
||||
if (host && host->getNegative()) {
|
||||
return (ConstHostPtr());
|
||||
}
|
||||
return (host);
|
||||
}
|
||||
@ -252,57 +377,121 @@ ConstHostPtr
|
||||
HostMgr::get6(const SubnetID& subnet_id,
|
||||
const asiolink::IOAddress& addr) const {
|
||||
ConstHostPtr host = getCfgHosts()->get6(subnet_id, addr);
|
||||
if (!host && alternate_source_) {
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
|
||||
HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_ADDRESS6)
|
||||
.arg(subnet_id)
|
||||
.arg(addr.toText());
|
||||
host = alternate_source_->get6(subnet_id, addr);
|
||||
if (host || alternate_sources_.empty()) {
|
||||
return (host);
|
||||
}
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
|
||||
HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_ADDRESS6)
|
||||
.arg(subnet_id)
|
||||
.arg(addr.toText());
|
||||
for (auto it = alternate_sources_.begin();
|
||||
!host && it != alternate_sources_.end(); ++it) {
|
||||
host = (*it)->get6(subnet_id, addr);
|
||||
if (host && cache_ptr_ && (it != alternate_sources_.begin())) {
|
||||
cache(host);
|
||||
}
|
||||
}
|
||||
if (host && host->getNegative()) {
|
||||
return (ConstHostPtr());
|
||||
}
|
||||
return (host);
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
HostMgr::add(const HostPtr& host) {
|
||||
if (!alternate_source_) {
|
||||
if (alternate_sources_.empty()) {
|
||||
isc_throw(NoHostDataSourceManager, "Unable to add new host because there is "
|
||||
"no hosts-database configured.");
|
||||
}
|
||||
alternate_source_->add(host);
|
||||
for (auto it = alternate_sources_.begin();
|
||||
it != alternate_sources_.end(); ++it) {
|
||||
if ((*it)->add(host)) {
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
// This should never happen as at least one backend implements addition.
|
||||
return (false);
|
||||
}
|
||||
|
||||
bool
|
||||
HostMgr::del(const SubnetID& subnet_id, const asiolink::IOAddress& addr) {
|
||||
if (!alternate_source_) {
|
||||
if (alternate_sources_.empty()) {
|
||||
isc_throw(NoHostDataSourceManager, "Unable to delete a host because there is "
|
||||
"no hosts-database configured.");
|
||||
}
|
||||
|
||||
return (alternate_source_->del(subnet_id, addr));
|
||||
for (auto it = alternate_sources_.begin();
|
||||
it != alternate_sources_.end(); ++it) {
|
||||
if ((*it)->del(subnet_id, addr)) {
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
bool
|
||||
HostMgr::del4(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin, const size_t identifier_len) {
|
||||
if (!alternate_source_) {
|
||||
if (alternate_sources_.empty()) {
|
||||
isc_throw(NoHostDataSourceManager, "Unable to delete a host because there is "
|
||||
"no hosts-database configured.");
|
||||
}
|
||||
|
||||
return (alternate_source_->del4(subnet_id, identifier_type,
|
||||
identifier_begin, identifier_len));
|
||||
for (auto it = alternate_sources_.begin();
|
||||
it != alternate_sources_.end(); ++it) {
|
||||
if ((*it)->del4(subnet_id, identifier_type,
|
||||
identifier_begin, identifier_len)) {
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
bool
|
||||
HostMgr::del6(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin, const size_t identifier_len) {
|
||||
if (!alternate_source_) {
|
||||
if (alternate_sources_.empty()) {
|
||||
isc_throw(NoHostDataSourceManager, "unable to delete a host because there is "
|
||||
"no alternate host data source present");
|
||||
}
|
||||
|
||||
return (alternate_source_->del6(subnet_id, identifier_type,
|
||||
identifier_begin, identifier_len));
|
||||
for (auto it = alternate_sources_.begin();
|
||||
it != alternate_sources_.end(); ++it) {
|
||||
if ((*it)->del6(subnet_id, identifier_type,
|
||||
identifier_begin, identifier_len)) {
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
void
|
||||
HostMgr::cache(ConstHostPtr host) const {
|
||||
if (cache_ptr_) {
|
||||
// Replace any existing value.
|
||||
int overwrite = 0;
|
||||
// Don't check the result as it does not matter?
|
||||
cache_ptr_->insert(host, overwrite);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HostMgr::cacheNegative(const SubnetID& ipv4_subnet_id,
|
||||
const SubnetID& ipv6_subnet_id,
|
||||
const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin,
|
||||
const size_t identifier_len) const {
|
||||
if (cache_ptr_ && negative_caching_) {
|
||||
HostPtr host(new Host(identifier_begin, identifier_len,
|
||||
identifier_type,
|
||||
ipv4_subnet_id, ipv6_subnet_id,
|
||||
IOAddress::IPV4_ZERO_ADDRESS()));
|
||||
host->setNegative(true);
|
||||
// Don't replace any existing value.
|
||||
int overwrite = -1;
|
||||
// nor matter if it fails.
|
||||
cache_ptr_->insert(host, overwrite);
|
||||
}
|
||||
}
|
||||
|
||||
} // end of isc::dhcp namespace
|
||||
|
@ -1,4 +1,4 @@
|
||||
// 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
|
||||
@ -10,6 +10,7 @@
|
||||
#include <dhcp/duid.h>
|
||||
#include <dhcp/hwaddr.h>
|
||||
#include <dhcpsrv/base_host_data_source.h>
|
||||
#include <dhcpsrv/cache_host_data_source.h>
|
||||
#include <dhcpsrv/host.h>
|
||||
#include <dhcpsrv/subnet_id.h>
|
||||
#include <boost/noncopyable.hpp>
|
||||
@ -33,42 +34,62 @@ namespace dhcp {
|
||||
/// configuration, accessible through the @c CfgHosts object in the @c CfgMgr.
|
||||
/// The @c CfgHosts object holds all reservations specified in the DHCP server
|
||||
/// configuration file. If a particular reservation is not found in the
|
||||
/// @c CfgHosts object, the @c HostMgr will try to find it using the alternate
|
||||
/// host data storage. The alternate host data storage is usually a database
|
||||
/// @c CfgHosts object, the @c HostMgr will try to find it using alternate
|
||||
/// host data storages. An alternate host data storage is usually a database
|
||||
/// (e.g. SQL database), accessible through a dedicated host data source
|
||||
/// object (a.k.a. database backend). This datasource is responsible for
|
||||
/// managing the connection with the database and forming appropriate queries
|
||||
/// to retrieve (or update) the information about the reservations.
|
||||
///
|
||||
/// The use of the alternate host data source is optional and usually requires
|
||||
/// The use of alternate host data sources is optional and usually requires
|
||||
/// additional configuration to be specified by the server administrator.
|
||||
/// For example, for the SQL database the user's credentials, database address,
|
||||
/// and database name are required. The @c HostMgr passes these parameters
|
||||
/// to an appropriate datasource which is responsible for opening a connection
|
||||
/// and maintaining it.
|
||||
///
|
||||
/// It is possible to switch to a different alternate data source or disable
|
||||
/// the use of the alternate datasource, e.g. as a result of server's
|
||||
/// It is possible to switch to different alternate data sources or disable
|
||||
/// the use of alternate datasources, e.g. as a result of server's
|
||||
/// reconfiguration. However, the use of the primary host data source (i.e.
|
||||
/// reservations specified in the configuration file) can't be disabled.
|
||||
///
|
||||
/// @todo Implement alternate host data sources: MySQL, PostgreSQL, etc.
|
||||
class HostMgr : public boost::noncopyable, public BaseHostDataSource {
|
||||
public:
|
||||
|
||||
/// @brief Creates new instance of the @c HostMgr.
|
||||
///
|
||||
/// If an instance of the @c HostMgr already exists, it will be replaced
|
||||
/// by the new instance. Thus, any instances of the alternate host data
|
||||
/// by the new instance. Thus, any instances of alternate host data
|
||||
/// sources will be dropped.
|
||||
///
|
||||
static void create();
|
||||
|
||||
/// @brief Add an alternate host data source.
|
||||
///
|
||||
/// @param access Host data source access parameters for the alternate
|
||||
/// host data source. It holds "keyword=value" pairs, separated by spaces.
|
||||
/// The supported values are specific to the alternate data source in use.
|
||||
/// However, the "type" parameter will be common and it will specify which
|
||||
/// data source is to be used. Currently, no parameters are supported
|
||||
/// and the parameter is ignored.
|
||||
static void create(const std::string& access = "");
|
||||
static void addSource(const std::string& access);
|
||||
|
||||
/// @brief Delete an alternate host data source.
|
||||
///
|
||||
/// @param db_type_type database backend type.
|
||||
/// @return true when found and removed, false when not found.
|
||||
static bool delSource(const std::string& db_type);
|
||||
|
||||
/// @brief Delete all alternate host data source.
|
||||
static void delAllSources();
|
||||
|
||||
/// @brief Check for the cache host data source.
|
||||
///
|
||||
/// Checks if the first host data source implements
|
||||
/// the cache abstract class and sets cache_ptr_.
|
||||
///
|
||||
/// @param logging When true (not the default) emit an informational log.
|
||||
/// @return true if the first host data source is a cache.
|
||||
static bool checkCacheSource(bool logging = false);
|
||||
|
||||
/// @brief Returns a sole instance of the @c HostMgr.
|
||||
///
|
||||
@ -159,6 +180,28 @@ public:
|
||||
get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr,
|
||||
const DuidPtr& duid = DuidPtr()) const;
|
||||
|
||||
/// @brief Returns any host connected to the IPv4 subnet.
|
||||
///
|
||||
/// This method returns a single reservation for a particular host as
|
||||
/// documented in the @c BaseHostDataSource::get4 even when the
|
||||
/// reservation is marked as from negative caching. This allows to
|
||||
/// overload negative caching with extra information in the user
|
||||
/// context.
|
||||
///
|
||||
/// @param subnet_id Subnet identifier.
|
||||
/// @param identifier_type Identifier type.
|
||||
/// @param identifier_begin Pointer to a beginning of a buffer containing
|
||||
/// an identifier.
|
||||
/// @param identifier_len Identifier length.
|
||||
///
|
||||
/// @return Const @c Host object for which reservation has been made using
|
||||
/// the specified identifier.
|
||||
virtual ConstHostPtr
|
||||
get4Any(const SubnetID& subnet_id,
|
||||
const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin,
|
||||
const size_t identifier_len) const;
|
||||
|
||||
/// @brief Returns a host connected to the IPv4 subnet.
|
||||
///
|
||||
/// This method returns a single reservation for a particular host as
|
||||
@ -206,6 +249,28 @@ public:
|
||||
get6(const SubnetID& subnet_id, const DuidPtr& duid,
|
||||
const HWAddrPtr& hwaddr = HWAddrPtr()) const;
|
||||
|
||||
/// @brief Returns any host connected to the IPv6 subnet.
|
||||
///
|
||||
/// This method returns a host connected to the IPv6 subnet as described
|
||||
/// in the @c BaseHostDataSource::get6 even when the
|
||||
/// reservation is marked as from negative caching. This allows to
|
||||
/// overload negative caching with extra information in the user
|
||||
/// context.
|
||||
///
|
||||
/// @param subnet_id Subnet identifier.
|
||||
/// @param identifier_type Identifier type.
|
||||
/// @param identifier_begin Pointer to a beginning of a buffer containing
|
||||
/// an identifier.
|
||||
/// @param identifier_len Identifier length.
|
||||
///
|
||||
/// @return Const @c Host object for which reservation has been made using
|
||||
/// the specified identifier.
|
||||
virtual ConstHostPtr
|
||||
get6Any(const SubnetID& subnet_id,
|
||||
const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin,
|
||||
const size_t identifier_len) const;
|
||||
|
||||
/// @brief Returns a host connected to the IPv6 subnet.
|
||||
///
|
||||
/// This method returns a host connected to the IPv6 subnet as described
|
||||
@ -250,40 +315,8 @@ public:
|
||||
/// in use.
|
||||
///
|
||||
/// @param host Pointer to the new @c Host object being added.
|
||||
virtual void add(const HostPtr& host);
|
||||
|
||||
/// @brief Return backend type
|
||||
///
|
||||
/// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
|
||||
///
|
||||
/// @return Type of the backend.
|
||||
virtual std::string getType() const {
|
||||
return (std::string("host_mgr"));
|
||||
}
|
||||
|
||||
/// @brief Returns pointer to the host data source
|
||||
///
|
||||
/// May return NULL
|
||||
/// @return pointer to the host data source (or NULL)
|
||||
HostDataSourcePtr getHostDataSource() const {
|
||||
return (alternate_source_);
|
||||
}
|
||||
|
||||
/// @brief Sets the alternate host data source.
|
||||
///
|
||||
/// Note: This should be used only for testing. Do not use
|
||||
/// in production. Normal control flow assumes that
|
||||
/// HostMgr::create(...) is called and it instantiates
|
||||
/// appropriate host data source. However, some tests
|
||||
/// (e.g. host_cmds) implement their own very simple
|
||||
/// data source. It's not production ready by any means,
|
||||
/// so it does not belong in host_data_source_factory.cc.
|
||||
/// The testing nature of this method is reflected in its name.
|
||||
///
|
||||
/// @param source new source to be set (may be NULL)
|
||||
void setTestHostDataSource(const HostDataSourcePtr& source) {
|
||||
alternate_source_ = source;
|
||||
}
|
||||
/// @return true if addition was successful.
|
||||
virtual bool add(const HostPtr& host);
|
||||
|
||||
/// @brief Attempts to delete a host by address.
|
||||
///
|
||||
@ -322,15 +355,76 @@ public:
|
||||
del6(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin, const size_t identifier_len);
|
||||
|
||||
/// @brief Return backend type
|
||||
///
|
||||
/// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
|
||||
///
|
||||
/// @return Type of the backend.
|
||||
virtual std::string getType() const {
|
||||
return (std::string("host_mgr"));
|
||||
}
|
||||
|
||||
/// @brief Returns the host data source list.
|
||||
///
|
||||
/// @return reference to the host data source list.
|
||||
HostDataSourceList& getHostDataSourceList() {
|
||||
return (alternate_sources_);
|
||||
}
|
||||
|
||||
/// @brief Returns the first host data source.
|
||||
///
|
||||
/// May return NULL if the host data source list is empty.
|
||||
/// @return pointer to the first host data source (or NULL).
|
||||
HostDataSourcePtr getHostDataSource() const;
|
||||
|
||||
/// @brief Returns the negative caching flag.
|
||||
///
|
||||
/// @return the negative caching flag.
|
||||
bool getNegativeCaching() const {
|
||||
return (negative_caching_);
|
||||
}
|
||||
|
||||
/// @brief Sets the negative caching flag.
|
||||
///
|
||||
void setNegativeCaching(bool negative_caching) {
|
||||
negative_caching_ = negative_caching;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @brief The negative caching flag.
|
||||
///
|
||||
/// When true and the first data source is a cache negative answers
|
||||
/// to get[46] for aubnet and identifier are cached.
|
||||
bool negative_caching_;
|
||||
|
||||
/// @brief Cache an answer.
|
||||
///
|
||||
/// @param host Pointer to the missied host.
|
||||
virtual void cache(ConstHostPtr host) const;
|
||||
|
||||
/// @brief Cache a negative answer.
|
||||
///
|
||||
/// @param ipv4_subnet_id Identifier of the IPv4 subnet.
|
||||
/// @param ipv6_subnet_id Identifier of the IPv6 subnet.
|
||||
/// @param identifier_type Identifier type.
|
||||
/// @param identifier_begin Pointer to a beginning of the Identifier.
|
||||
/// @param identifier_len Identifier length.
|
||||
virtual void cacheNegative(const SubnetID& ipv4_subnet_id,
|
||||
const SubnetID& ipv6_subnet_id,
|
||||
const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin,
|
||||
const size_t identifier_len) const;
|
||||
|
||||
private:
|
||||
|
||||
/// @brief Private default constructor.
|
||||
HostMgr() { }
|
||||
HostMgr() : negative_caching_(false) { }
|
||||
|
||||
/// @brief Pointer to an alternate host data source.
|
||||
///
|
||||
/// If this pointer is NULL, the source is not in use.
|
||||
HostDataSourcePtr alternate_source_;
|
||||
/// @brief List of alternate host data sources.
|
||||
HostDataSourceList alternate_sources_;
|
||||
|
||||
/// @brief Pointer to the cache.
|
||||
CacheHostDataSourcePtr cache_ptr_;
|
||||
|
||||
/// @brief Returns a pointer to the currently used instance of the
|
||||
/// @c HostMgr.
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
# Copyright (C) 2015-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
|
||||
@ -11,6 +11,10 @@ This debug message is issued when new host (with reservations) is added to
|
||||
the server's configuration. The argument describes the host and its
|
||||
reservations in detail.
|
||||
|
||||
% HOSTS_CFG_CACHE_HOST_DATA_SOURCE get host cache data source: %1
|
||||
This informational message is issued when a host cache data source is
|
||||
detected by the host manager.
|
||||
|
||||
% HOSTS_CFG_CLOSE_HOST_DATA_SOURCE Closing host data source: %1
|
||||
This is a normal message being printed when the server closes host data
|
||||
source connection.
|
||||
@ -134,24 +138,24 @@ subnet id and specific host identifier.
|
||||
This debug message is issued when no host was found using the specified
|
||||
subnet id and host identifier.
|
||||
|
||||
% HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_ADDRESS4 trying alternate source for host using subnet id %1 and address %2
|
||||
% HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_ADDRESS4 trying alternate sources for host using subnet id %1 and address %2
|
||||
This debug message is issued when the Host Manager doesn't find the
|
||||
host connected to the specific subnet and having the reservation for
|
||||
the specific IPv4 address, and it is starting to search for this host
|
||||
in the alternate host data source.
|
||||
in alternate host data sources.
|
||||
|
||||
% HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_HWADDR_DUID trying alternate source for host using subnet id %1, HWADDR %2, DUID%3
|
||||
% HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_HWADDR_DUID trying alternate sources for host using subnet id %1, HWADDR %2, DUID%3
|
||||
This debug message is issued when the Host Manager doesn't find the
|
||||
host connected to the specific subnet and identified by the HW address
|
||||
or DUID, and it is starting to search for this host in the alternate
|
||||
host data source.
|
||||
or DUID, and it is starting to search for this host in alternate
|
||||
host data sources.
|
||||
|
||||
% HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_IDENTIFIER get one host with IPv4 reservation for subnet id %1, identified by %2
|
||||
This debug message is issued when starting to retrieve a host holding
|
||||
IPv4 reservation, which is connected to a specific subnet and
|
||||
is identified by a specific unique identifier.
|
||||
|
||||
% HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_IDENTIFIER_HOST using subnet id %1 and identifier %2, found host: %3
|
||||
% HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_IDENTIFIER_HOST using subnet id %1 and identifier %2, found in %3 host: %4
|
||||
This debug message includes the details of a host returned by an
|
||||
alternate hosts data source using a subnet id and specific host
|
||||
identifier.
|
||||
@ -160,32 +164,32 @@ identifier.
|
||||
This debug message is issued when no host was found using the specified
|
||||
subnet id and host identifier.
|
||||
|
||||
% HOSTS_MGR_ALTERNATE_GET6_PREFIX trying alternate source for host using prefix %1/%2
|
||||
% HOSTS_MGR_ALTERNATE_GET6_PREFIX trying alternate sources for host using prefix %1/%2
|
||||
This debug message is issued when the Host Manager doesn't find the
|
||||
host connected to the specific subnet and having the reservation for
|
||||
the specified prefix, and it is starting to search for this host in
|
||||
the alternate host data source.
|
||||
alternate host data sources.
|
||||
|
||||
% HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_ADDRESS6 trying alternate source for host using subnet id %1 and IPv6 address %2
|
||||
% HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_ADDRESS6 trying alternate sources for host using subnet id %1 and IPv6 address %2
|
||||
This debug message is issued when the Host Manager doesn't find the
|
||||
host connected to the specific subnet and having the reservation for
|
||||
the specified IPv6 address, and it is starting to search for this
|
||||
host in the alternate host data source.
|
||||
host in alternate host data sources.
|
||||
|
||||
% HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_DUID_HWADDR trying alternate source for host using subnet id %1, DUID %2, HWADDR %3
|
||||
% HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_DUID_HWADDR trying alternate sources for host using subnet id %1, DUID %2, HWADDR %3
|
||||
This debug message is issued when the Host Manager doesn't find the
|
||||
host connected to the specific subnet and identified by the specified
|
||||
DUID or HW Address, and it is starting to search for this host in the
|
||||
alternate host data source.
|
||||
DUID or HW Address, and it is starting to search for this host in
|
||||
alternate host data sources.
|
||||
|
||||
% HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_IDENTIFIER get one host with IPv6 reservation for subnet id %1, identified by %2
|
||||
This debug message is issued when starting to retrieve a host holding
|
||||
IPv4 reservation, which is connected to a specific subnet and
|
||||
is identified by a specific unique identifier.
|
||||
|
||||
% HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_IDENTIFIER_HOST using subnet id %1 and identifier %2, found host: %3
|
||||
% HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_IDENTIFIER_HOST using subnet id %1 and identifier %2, found in %3 host: %4
|
||||
This debug message includes the details of a host returned by an
|
||||
alternate hosts data source using a subnet id and specific host
|
||||
alternate host data source using a subnet id and specific host
|
||||
identifier.
|
||||
|
||||
% HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_IDENTIFIER_NULL host not found using subnet id %1 and identifier %2
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2012-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2012-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
|
||||
@ -103,9 +103,10 @@ database. This object must implement the \ref isc::dhcp::BaseHostDataSource
|
||||
interface and its implementation is specific to the type of storage
|
||||
holding the reservations. For example, the host data source managing
|
||||
host reservations in the MySQL database is required to establish
|
||||
connection to the MySQL database and issue specific queries. Once
|
||||
implemented, the \ref isc::dhcp::HostMgr::create method must be updated
|
||||
to create an instance of this datasource. Note, that this instance is
|
||||
connection to the MySQL database and issue specific queries. A factory
|
||||
method creating an instance of a base host data source object must be
|
||||
registered (at global object initialization for built-in backends,
|
||||
dynamically for backends loaded at run-time). Note, that this instance is
|
||||
created as "alternate host data source" as opposed to the primary data
|
||||
source which returns host reservations specified in the configuration file.
|
||||
The primary data source is implemented internally in the
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2015-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
|
||||
@ -2562,7 +2562,7 @@ MySqlHostDataSource::~MySqlHostDataSource() {
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
MySqlHostDataSource::add(const HostPtr& host) {
|
||||
// If operating in read-only mode, throw exception.
|
||||
impl_->checkReadOnly();
|
||||
@ -2607,6 +2607,8 @@ MySqlHostDataSource::add(const HostPtr& host) {
|
||||
|
||||
// Everything went fine, so explicitly commit the transaction.
|
||||
transaction.commit();
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2015-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
|
||||
@ -223,7 +223,8 @@ public:
|
||||
/// one instance is identified by HW address, another one by DUID.
|
||||
///
|
||||
/// @param host Pointer to the new @c Host object being added.
|
||||
virtual void add(const HostPtr& host);
|
||||
/// @return true as addition is successful or throws.
|
||||
virtual bool add(const HostPtr& host);
|
||||
|
||||
/// @brief Attempts to delete a host by (subnet-id, address)
|
||||
///
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2012-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2012-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
|
||||
@ -30,7 +30,7 @@ namespace dhcp {
|
||||
|
||||
|
||||
// Factory function to build the parser
|
||||
DbAccessParser::DbAccessParser(DBType db_type)
|
||||
DbAccessParser::DbAccessParser(size_t db_type)
|
||||
: values_(), type_(db_type) {
|
||||
}
|
||||
|
||||
@ -110,7 +110,8 @@ DbAccessParser::parse(CfgDbAccessPtr& cfg_db,
|
||||
// a. Check if the "type" keyword exists and thrown an exception if not.
|
||||
StringPairMap::const_iterator type_ptr = values_copy.find("type");
|
||||
if (type_ptr == values_copy.end()) {
|
||||
isc_throw(DhcpConfigError, (type_ == LEASE_DB ? "lease" : "host")
|
||||
isc_throw(DhcpConfigError,
|
||||
(type_ == CfgDbAccess::LEASE_DB ? "lease" : "host")
|
||||
<< " database access parameters must "
|
||||
"include the keyword 'type' to determine type of database "
|
||||
"to be accessed (" << database_config->getPosition() << ")");
|
||||
@ -167,10 +168,12 @@ DbAccessParser::parse(CfgDbAccessPtr& cfg_db,
|
||||
values_.swap(values_copy);
|
||||
|
||||
// 5. Save the database access string in the Configuration Manager.
|
||||
if (type_ == LEASE_DB) {
|
||||
if (type_ == CfgDbAccess::LEASE_DB) {
|
||||
cfg_db->setLeaseDbAccessString(getDbAccessString());
|
||||
} else if (type_ == HOSTS_DB) {
|
||||
} else if (type_ == CfgDbAccess::HOSTS_DB) {
|
||||
cfg_db->setHostDbAccessString(getDbAccessString());
|
||||
} else if (type_ > CfgDbAccess::HOSTS_DB) {
|
||||
cfg_db->pushHostDbAccessString(getDbAccessString());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2012-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2012-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
|
||||
@ -28,12 +28,6 @@ namespace dhcp {
|
||||
class DbAccessParser: public isc::data::SimpleParser {
|
||||
public:
|
||||
|
||||
/// @brief Specifies the database type
|
||||
typedef enum {
|
||||
LEASE_DB = 1,
|
||||
HOSTS_DB = 2
|
||||
} DBType;
|
||||
|
||||
/// @brief Keyword and associated value
|
||||
typedef std::pair<std::string, std::string> StringPair;
|
||||
|
||||
@ -43,7 +37,7 @@ public:
|
||||
/// @brief Constructor
|
||||
///
|
||||
/// @param db_type Specifies database type (lease or hosts)
|
||||
explicit DbAccessParser(DBType db_type);
|
||||
explicit DbAccessParser(size_t db_type);
|
||||
|
||||
/// The destructor.
|
||||
virtual ~DbAccessParser()
|
||||
@ -98,7 +92,7 @@ private:
|
||||
|
||||
std::map<std::string, std::string> values_; ///< Stored parameter values
|
||||
|
||||
DBType type_; ///< Database type (leases or hosts)
|
||||
size_t type_; ///< Database type (leases or hosts)
|
||||
};
|
||||
|
||||
}; // namespace dhcp
|
||||
|
@ -1934,7 +1934,7 @@ PgSqlHostDataSource::~PgSqlHostDataSource() {
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
PgSqlHostDataSource::add(const HostPtr& host) {
|
||||
// If operating in read-only mode, throw exception.
|
||||
impl_->checkReadOnly();
|
||||
@ -1977,6 +1977,8 @@ PgSqlHostDataSource::add(const HostPtr& host) {
|
||||
|
||||
// Everything went fine, so explicitly commit the transaction.
|
||||
transaction.commit();
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2016-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
|
||||
@ -247,9 +247,10 @@ public:
|
||||
/// -# Address and Prefix Length must be unique (DuplicateEntry)
|
||||
///
|
||||
/// @param host Pointer to the new @c Host object being added.
|
||||
/// @return true as addition is successful or throws.
|
||||
/// @throw DuplicateEntry or DbOperationError dependent on the constraint
|
||||
/// violation
|
||||
virtual void add(const HostPtr& host);
|
||||
virtual bool add(const HostPtr& host);
|
||||
|
||||
/// @brief Attempts to delete a host by (subnet-id, address)
|
||||
///
|
||||
|
@ -1,4 +1,4 @@
|
||||
// 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
|
||||
@ -342,12 +342,11 @@ SrvConfig::toElement() const {
|
||||
// Set lease-database
|
||||
CfgLeaseDbAccess lease_db(*cfg_db_access_);
|
||||
dhcp->set("lease-database", lease_db.toElement());
|
||||
// Set hosts-database
|
||||
// Set hosts-databases
|
||||
CfgHostDbAccess host_db(*cfg_db_access_);
|
||||
// @todo accept empty map
|
||||
ConstElementPtr hosts_database = host_db.toElement();
|
||||
if (hosts_database->size() > 0) {
|
||||
dhcp->set("hosts-database", hosts_database);
|
||||
ConstElementPtr hosts_databases = host_db.toElement();
|
||||
if (hosts_databases->size() > 0) {
|
||||
dhcp->set("hosts-databases", hosts_databases);
|
||||
}
|
||||
// Set host-reservation-identifiers
|
||||
ConstElementPtr host_ids;
|
||||
|
@ -91,6 +91,7 @@ libdhcpsrv_unittests_SOURCES += dbaccess_parser_unittest.cc
|
||||
libdhcpsrv_unittests_SOURCES += dhcp4o6_ipc_unittest.cc
|
||||
libdhcpsrv_unittests_SOURCES += duid_config_parser_unittest.cc
|
||||
libdhcpsrv_unittests_SOURCES += expiration_config_parser_unittest.cc
|
||||
libdhcpsrv_unittests_SOURCES += host_data_source_factory_unittest.cc
|
||||
libdhcpsrv_unittests_SOURCES += host_mgr_unittest.cc
|
||||
libdhcpsrv_unittests_SOURCES += host_unittest.cc
|
||||
libdhcpsrv_unittests_SOURCES += host_reservation_parser_unittest.cc
|
||||
@ -103,7 +104,6 @@ libdhcpsrv_unittests_SOURCES += lease_mgr_unittest.cc
|
||||
libdhcpsrv_unittests_SOURCES += logging_unittest.cc
|
||||
libdhcpsrv_unittests_SOURCES += logging_info_unittest.cc
|
||||
libdhcpsrv_unittests_SOURCES += generic_lease_mgr_unittest.cc generic_lease_mgr_unittest.h
|
||||
libdhcpsrv_unittests_SOURCES += generic_host_data_source_unittest.cc generic_host_data_source_unittest.h
|
||||
libdhcpsrv_unittests_SOURCES += memfile_lease_mgr_unittest.cc
|
||||
libdhcpsrv_unittests_SOURCES += dhcp_parsers_unittest.cc
|
||||
if HAVE_MYSQL
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2016-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
|
||||
@ -30,7 +30,7 @@ TEST(CfgDbAccessTest, defaults) {
|
||||
runToElementTest<CfgLeaseDbAccess>(expected, CfgLeaseDbAccess(cfg));
|
||||
|
||||
EXPECT_TRUE(cfg.getHostDbAccessString().empty());
|
||||
runToElementTest<CfgHostDbAccess>("{ }", CfgHostDbAccess(cfg));
|
||||
runToElementTest<CfgHostDbAccess>("[ ]", CfgHostDbAccess(cfg));
|
||||
}
|
||||
|
||||
// This test verifies that it is possible to set the lease database
|
||||
@ -65,7 +65,7 @@ TEST(CfgDbAccessTest, setHostDbAccessString) {
|
||||
EXPECT_EQ("type=mysql", cfg.getHostDbAccessString());
|
||||
|
||||
// Check unparse
|
||||
std::string expected = "{ \"type\": \"mysql\" }";
|
||||
std::string expected = "[ { \"type\": \"mysql\" } ]";
|
||||
runToElementTest<CfgHostDbAccess>(expected, CfgHostDbAccess(cfg));
|
||||
|
||||
// Append additional parameter.
|
||||
@ -80,6 +80,39 @@ TEST(CfgDbAccessTest, setHostDbAccessString) {
|
||||
EXPECT_TRUE(cfg.getHostDbAccessString().empty());
|
||||
}
|
||||
|
||||
// This test verifies that it is possible to set multiple host
|
||||
// database string.
|
||||
TEST(CfgDbAccessTest, pushHostDbAccessString) {
|
||||
CfgDbAccess cfg;
|
||||
ASSERT_NO_THROW(cfg.setHostDbAccessString("type=mysql"));
|
||||
EXPECT_EQ("type=mysql", cfg.getHostDbAccessString());
|
||||
|
||||
// Push two other strings
|
||||
ASSERT_NO_THROW(cfg.pushHostDbAccessString("type=foo"));
|
||||
ASSERT_NO_THROW(cfg.pushHostDbAccessString("type=bar"));
|
||||
|
||||
// Check unparse
|
||||
std::string expected = "[ { \"type\": \"mysql\" }, ";
|
||||
expected += "{ \"type\": \"foo\" }, { \"type\": \"bar\" } ]";
|
||||
runToElementTest<CfgHostDbAccess>(expected, CfgHostDbAccess(cfg));
|
||||
|
||||
// Check access strings
|
||||
std::vector<std::string> hal = cfg.getHostDbAccessStringList();
|
||||
ASSERT_EQ(3, hal.size());
|
||||
EXPECT_EQ("type=mysql", hal[0]);
|
||||
EXPECT_EQ("type=foo", hal[1]);
|
||||
EXPECT_EQ("type=bar", hal[2]);
|
||||
|
||||
// Reset the first string so it will be ignored.
|
||||
ASSERT_NO_THROW(cfg.setHostDbAccessString(""));
|
||||
expected = "[ { \"type\": \"foo\" }, { \"type\": \"bar\" } ]";
|
||||
runToElementTest<CfgHostDbAccess>(expected, CfgHostDbAccess(cfg));
|
||||
hal = cfg.getHostDbAccessStringList();
|
||||
ASSERT_EQ(2, hal.size());
|
||||
EXPECT_EQ("type=foo", hal[0]);
|
||||
EXPECT_EQ("type=bar", hal[1]);
|
||||
}
|
||||
|
||||
// Tests that lease manager can be created from a specified configuration.
|
||||
TEST(CfgDbAccessTest, createLeaseMgr) {
|
||||
CfgDbAccess cfg;
|
||||
@ -129,8 +162,8 @@ TEST_F(CfgMySQLDbAccessTest, createManagers) {
|
||||
});
|
||||
|
||||
ASSERT_NO_THROW({
|
||||
HostDataSourcePtr& host_data_source =
|
||||
HostDataSourceFactory::getHostDataSourcePtr();
|
||||
const HostDataSourcePtr& host_data_source =
|
||||
HostMgr::instance().getHostDataSource();
|
||||
ASSERT_TRUE(host_data_source);
|
||||
EXPECT_EQ("mysql", host_data_source->getType());
|
||||
});
|
||||
@ -142,8 +175,8 @@ TEST_F(CfgMySQLDbAccessTest, createManagers) {
|
||||
ASSERT_NO_THROW(HostMgr::instance());
|
||||
|
||||
ASSERT_NO_THROW({
|
||||
HostDataSourcePtr& host_data_source =
|
||||
HostDataSourceFactory::getHostDataSourcePtr();
|
||||
const HostDataSourcePtr& host_data_source =
|
||||
HostMgr::instance().getHostDataSource();
|
||||
ASSERT_TRUE(host_data_source);
|
||||
EXPECT_EQ("mysql", host_data_source->getType());
|
||||
});
|
||||
|
@ -22,8 +22,9 @@
|
||||
#include <dhcpsrv/cql_host_data_source.h>
|
||||
#include <dhcpsrv/cql_lease_mgr.h>
|
||||
#include <dhcpsrv/host.h>
|
||||
#include <dhcpsrv/host_mgr.h>
|
||||
#include <dhcpsrv/host_data_source_factory.h>
|
||||
#include <dhcpsrv/tests/generic_host_data_source_unittest.h>
|
||||
#include <dhcpsrv/testutils/generic_host_data_source_unittest.h>
|
||||
#include <dhcpsrv/tests/test_utils.h>
|
||||
#include <dhcpsrv/testutils/cql_schema.h>
|
||||
#include <dhcpsrv/testutils/host_data_source_utils.h>
|
||||
@ -54,7 +55,8 @@ public:
|
||||
|
||||
// Connect to the database
|
||||
try {
|
||||
HostDataSourceFactory::create(validCqlConnectionString());
|
||||
HostMgr::create();
|
||||
HostMgr::addSource(validCqlConnectionString());
|
||||
} catch (...) {
|
||||
std::cerr << "*** ERROR: unable to open database. The test"
|
||||
"*** environment is broken and must be fixed before"
|
||||
@ -64,7 +66,7 @@ public:
|
||||
throw;
|
||||
}
|
||||
|
||||
hdsptr_ = HostDataSourceFactory::getHostDataSourcePtr();
|
||||
hdsptr_ = HostMgr::instance().getHostDataSource();
|
||||
}
|
||||
|
||||
/// @brief Destroys the HDS and the schema.
|
||||
@ -75,7 +77,8 @@ public:
|
||||
// Rollback should never fail, as Cassandra doesn't support transactions
|
||||
// (commit and rollback are both no-op).
|
||||
}
|
||||
HostDataSourceFactory::destroy();
|
||||
HostMgr::delAllSources();
|
||||
hdsptr_.reset();
|
||||
destroyCqlSchema(false, true);
|
||||
}
|
||||
|
||||
@ -103,9 +106,9 @@ public:
|
||||
/// Parameter is ignored for CQL backend as the v4 and v6 leases share
|
||||
/// the same database.
|
||||
void reopen(Universe) {
|
||||
HostDataSourceFactory::destroy();
|
||||
HostDataSourceFactory::create(validCqlConnectionString());
|
||||
hdsptr_ = HostDataSourceFactory::getHostDataSourcePtr();
|
||||
HostMgr::create();
|
||||
HostMgr::addSource(validCqlConnectionString());
|
||||
hdsptr_ = HostMgr::instance().getHostDataSource();
|
||||
}
|
||||
};
|
||||
|
||||
@ -124,9 +127,9 @@ TEST(CqlHostDataSource, OpenDatabase) {
|
||||
// Check that lease manager open the database opens correctly and tidy up.
|
||||
// If it fails, print the error message.
|
||||
try {
|
||||
HostDataSourceFactory::create(validCqlConnectionString());
|
||||
EXPECT_NO_THROW((void)HostDataSourceFactory::getHostDataSourcePtr());
|
||||
HostDataSourceFactory::destroy();
|
||||
HostMgr::create();
|
||||
EXPECT_NO_THROW(HostMgr::addSource(validCqlConnectionString()));
|
||||
HostMgr::delSource("cql");
|
||||
} catch (const isc::Exception& ex) {
|
||||
FAIL() << "*** ERROR: unable to open database, reason:\n"
|
||||
<< " " << ex.what() << "\n"
|
||||
@ -139,9 +142,9 @@ TEST(CqlHostDataSource, OpenDatabase) {
|
||||
try {
|
||||
std::string connection_string = validCqlConnectionString() + std::string(" ") +
|
||||
std::string(VALID_TIMEOUT);
|
||||
HostDataSourceFactory::create(connection_string);
|
||||
EXPECT_NO_THROW((void)HostDataSourceFactory::getHostDataSourcePtr());
|
||||
HostDataSourceFactory::destroy();
|
||||
HostMgr::create();
|
||||
EXPECT_NO_THROW(HostMgr::addSource(connection_string));
|
||||
HostMgr::delSource("cql");
|
||||
} catch (const isc::Exception& ex) {
|
||||
FAIL() << "*** ERROR: unable to open database, reason:\n"
|
||||
<< " " << ex.what() << "\n"
|
||||
@ -151,39 +154,39 @@ TEST(CqlHostDataSource, OpenDatabase) {
|
||||
|
||||
// Check that attempting to get an instance of the host data source when
|
||||
// none is set throws an exception.
|
||||
EXPECT_FALSE(HostDataSourceFactory::getHostDataSourcePtr());
|
||||
EXPECT_FALSE(HostMgr::instance().getHostDataSource());
|
||||
|
||||
// Check that wrong specification of backend throws an exception.
|
||||
// (This is really a check on HostDataSourceFactory, but is convenient to
|
||||
// perform here.)
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(
|
||||
NULL, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
|
||||
InvalidParameter);
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(
|
||||
INVALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)),
|
||||
InvalidType);
|
||||
|
||||
// Check that invalid login data does not cause an exception, CQL should use
|
||||
// default values.
|
||||
EXPECT_NO_THROW(HostDataSourceFactory::create(connectionString(CQL_VALID_TYPE,
|
||||
EXPECT_NO_THROW(HostMgr::addSource(connectionString(CQL_VALID_TYPE,
|
||||
INVALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)));
|
||||
EXPECT_NO_THROW(HostDataSourceFactory::create(connectionString(CQL_VALID_TYPE,
|
||||
EXPECT_NO_THROW(HostMgr::addSource(connectionString(CQL_VALID_TYPE,
|
||||
VALID_NAME, INVALID_HOST, VALID_USER, VALID_PASSWORD)));
|
||||
EXPECT_NO_THROW(HostDataSourceFactory::create(connectionString(CQL_VALID_TYPE,
|
||||
EXPECT_NO_THROW(HostMgr::addSource(connectionString(CQL_VALID_TYPE,
|
||||
VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)));
|
||||
EXPECT_NO_THROW(HostDataSourceFactory::create(connectionString(CQL_VALID_TYPE,
|
||||
EXPECT_NO_THROW(HostMgr::addSource(connectionString(CQL_VALID_TYPE,
|
||||
VALID_NAME, VALID_HOST, VALID_USER, INVALID_PASSWORD)));
|
||||
|
||||
// Check that invalid timeouts throw DbOperationError.
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(CQL_VALID_TYPE,
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(CQL_VALID_TYPE,
|
||||
VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD, INVALID_TIMEOUT_1)),
|
||||
DbOperationError);
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(CQL_VALID_TYPE,
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(CQL_VALID_TYPE,
|
||||
VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD, INVALID_TIMEOUT_2)),
|
||||
DbOperationError);
|
||||
|
||||
// Check that CQL allows the hostname to not be specified.
|
||||
EXPECT_NO_THROW(HostDataSourceFactory::create(connectionString(CQL_VALID_TYPE,
|
||||
EXPECT_NO_THROW(HostMgr::addSource(connectionString(CQL_VALID_TYPE,
|
||||
NULL, VALID_HOST, INVALID_USER, VALID_PASSWORD)));
|
||||
|
||||
// Tidy up after the test
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2012-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2012-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
|
||||
@ -195,7 +195,7 @@ public:
|
||||
/// @brief Constructor
|
||||
///
|
||||
/// @brief Keyword/value collection of database access parameters
|
||||
TestDbAccessParser(DbAccessParser::DBType type)
|
||||
TestDbAccessParser(size_t type)
|
||||
: DbAccessParser(type)
|
||||
{}
|
||||
|
||||
@ -243,7 +243,7 @@ TEST_F(DbAccessParserTest, validTypeMemfile) {
|
||||
ConstElementPtr json_elements = Element::fromJSON(json_config);
|
||||
EXPECT_TRUE(json_elements);
|
||||
|
||||
TestDbAccessParser parser(DbAccessParser::LEASE_DB);
|
||||
TestDbAccessParser parser(CfgDbAccess::LEASE_DB);
|
||||
EXPECT_NO_THROW(parser.parse(json_elements));
|
||||
checkAccessString("Valid memfile", parser.getDbAccessParameters(), config);
|
||||
}
|
||||
@ -257,7 +257,7 @@ TEST_F(DbAccessParserTest, hosts) {
|
||||
ConstElementPtr json_elements = Element::fromJSON(json_config);
|
||||
EXPECT_TRUE(json_elements);
|
||||
|
||||
TestDbAccessParser parser(DbAccessParser::HOSTS_DB);
|
||||
TestDbAccessParser parser(CfgDbAccess::HOSTS_DB);
|
||||
EXPECT_NO_THROW(parser.parse(json_elements));
|
||||
checkAccessString("Valid memfile", parser.getDbAccessParameters(), config);
|
||||
}
|
||||
@ -273,7 +273,7 @@ TEST_F(DbAccessParserTest, emptyKeyword) {
|
||||
ConstElementPtr json_elements = Element::fromJSON(json_config);
|
||||
EXPECT_TRUE(json_elements);
|
||||
|
||||
TestDbAccessParser parser(DbAccessParser::LEASE_DB);
|
||||
TestDbAccessParser parser(CfgDbAccess::LEASE_DB);
|
||||
EXPECT_NO_THROW(parser.parse(json_elements));
|
||||
checkAccessString("Valid memfile", parser.getDbAccessParameters(), config);
|
||||
}
|
||||
@ -290,7 +290,7 @@ TEST_F(DbAccessParserTest, persistV4Memfile) {
|
||||
ConstElementPtr json_elements = Element::fromJSON(json_config);
|
||||
EXPECT_TRUE(json_elements);
|
||||
|
||||
TestDbAccessParser parser(DbAccessParser::LEASE_DB);
|
||||
TestDbAccessParser parser(CfgDbAccess::LEASE_DB);
|
||||
EXPECT_NO_THROW(parser.parse(json_elements));
|
||||
|
||||
checkAccessString("Valid memfile", parser.getDbAccessParameters(),
|
||||
@ -309,7 +309,7 @@ TEST_F(DbAccessParserTest, persistV6Memfile) {
|
||||
ConstElementPtr json_elements = Element::fromJSON(json_config);
|
||||
EXPECT_TRUE(json_elements);
|
||||
|
||||
TestDbAccessParser parser(DbAccessParser::LEASE_DB);
|
||||
TestDbAccessParser parser(CfgDbAccess::LEASE_DB);
|
||||
EXPECT_NO_THROW(parser.parse(json_elements));
|
||||
|
||||
checkAccessString("Valid memfile", parser.getDbAccessParameters(),
|
||||
@ -328,7 +328,7 @@ TEST_F(DbAccessParserTest, validLFCInterval) {
|
||||
ConstElementPtr json_elements = Element::fromJSON(json_config);
|
||||
EXPECT_TRUE(json_elements);
|
||||
|
||||
TestDbAccessParser parser(DbAccessParser::LEASE_DB);
|
||||
TestDbAccessParser parser(CfgDbAccess::LEASE_DB);
|
||||
EXPECT_NO_THROW(parser.parse(json_elements));
|
||||
checkAccessString("Valid LFC Interval", parser.getDbAccessParameters(),
|
||||
config);
|
||||
@ -346,7 +346,7 @@ TEST_F(DbAccessParserTest, negativeLFCInterval) {
|
||||
ConstElementPtr json_elements = Element::fromJSON(json_config);
|
||||
EXPECT_TRUE(json_elements);
|
||||
|
||||
TestDbAccessParser parser(DbAccessParser::LEASE_DB);
|
||||
TestDbAccessParser parser(CfgDbAccess::LEASE_DB);
|
||||
EXPECT_THROW(parser.parse(json_elements), DhcpConfigError);
|
||||
}
|
||||
|
||||
@ -362,7 +362,7 @@ TEST_F(DbAccessParserTest, largeLFCInterval) {
|
||||
ConstElementPtr json_elements = Element::fromJSON(json_config);
|
||||
EXPECT_TRUE(json_elements);
|
||||
|
||||
TestDbAccessParser parser(DbAccessParser::LEASE_DB);
|
||||
TestDbAccessParser parser(CfgDbAccess::LEASE_DB);
|
||||
EXPECT_THROW(parser.parse(json_elements), DhcpConfigError);
|
||||
}
|
||||
|
||||
@ -378,7 +378,7 @@ TEST_F(DbAccessParserTest, validTimeout) {
|
||||
ConstElementPtr json_elements = Element::fromJSON(json_config);
|
||||
EXPECT_TRUE(json_elements);
|
||||
|
||||
TestDbAccessParser parser(DbAccessParser::LEASE_DB);
|
||||
TestDbAccessParser parser(CfgDbAccess::LEASE_DB);
|
||||
EXPECT_NO_THROW(parser.parse(json_elements));
|
||||
checkAccessString("Valid timeout", parser.getDbAccessParameters(),
|
||||
config);
|
||||
@ -396,7 +396,7 @@ TEST_F(DbAccessParserTest, negativeTimeout) {
|
||||
ConstElementPtr json_elements = Element::fromJSON(json_config);
|
||||
EXPECT_TRUE(json_elements);
|
||||
|
||||
TestDbAccessParser parser(DbAccessParser::LEASE_DB);
|
||||
TestDbAccessParser parser(CfgDbAccess::LEASE_DB);
|
||||
EXPECT_THROW(parser.parse(json_elements), DhcpConfigError);
|
||||
}
|
||||
|
||||
@ -412,7 +412,7 @@ TEST_F(DbAccessParserTest, largeTimeout) {
|
||||
ConstElementPtr json_elements = Element::fromJSON(json_config);
|
||||
EXPECT_TRUE(json_elements);
|
||||
|
||||
TestDbAccessParser parser(DbAccessParser::LEASE_DB);
|
||||
TestDbAccessParser parser(CfgDbAccess::LEASE_DB);
|
||||
EXPECT_THROW(parser.parse(json_elements), DhcpConfigError);
|
||||
}
|
||||
|
||||
@ -428,7 +428,7 @@ TEST_F(DbAccessParserTest, validPort) {
|
||||
ConstElementPtr json_elements = Element::fromJSON(json_config);
|
||||
EXPECT_TRUE(json_elements);
|
||||
|
||||
TestDbAccessParser parser(DbAccessParser::LEASE_DB);
|
||||
TestDbAccessParser parser(CfgDbAccess::LEASE_DB);
|
||||
EXPECT_NO_THROW(parser.parse(json_elements));
|
||||
checkAccessString("Valid port", parser.getDbAccessParameters(),
|
||||
config);
|
||||
@ -446,7 +446,7 @@ TEST_F(DbAccessParserTest, negativePort) {
|
||||
ConstElementPtr json_elements = Element::fromJSON(json_config);
|
||||
EXPECT_TRUE(json_elements);
|
||||
|
||||
TestDbAccessParser parser(DbAccessParser::LEASE_DB);
|
||||
TestDbAccessParser parser(CfgDbAccess::LEASE_DB);
|
||||
EXPECT_THROW(parser.parse(json_elements), DhcpConfigError);
|
||||
}
|
||||
|
||||
@ -462,7 +462,7 @@ TEST_F(DbAccessParserTest, largePort) {
|
||||
ConstElementPtr json_elements = Element::fromJSON(json_config);
|
||||
EXPECT_TRUE(json_elements);
|
||||
|
||||
TestDbAccessParser parser(DbAccessParser::LEASE_DB);
|
||||
TestDbAccessParser parser(CfgDbAccess::LEASE_DB);
|
||||
EXPECT_THROW(parser.parse(json_elements), DhcpConfigError);
|
||||
}
|
||||
|
||||
@ -480,7 +480,7 @@ TEST_F(DbAccessParserTest, validTypeMysql) {
|
||||
ConstElementPtr json_elements = Element::fromJSON(json_config);
|
||||
EXPECT_TRUE(json_elements);
|
||||
|
||||
TestDbAccessParser parser(DbAccessParser::LEASE_DB);
|
||||
TestDbAccessParser parser(CfgDbAccess::LEASE_DB);
|
||||
EXPECT_NO_THROW(parser.parse(json_elements));
|
||||
checkAccessString("Valid mysql", parser.getDbAccessParameters(), config);
|
||||
}
|
||||
@ -498,7 +498,7 @@ TEST_F(DbAccessParserTest, missingTypeKeyword) {
|
||||
ConstElementPtr json_elements = Element::fromJSON(json_config);
|
||||
EXPECT_TRUE(json_elements);
|
||||
|
||||
TestDbAccessParser parser(DbAccessParser::LEASE_DB);
|
||||
TestDbAccessParser parser(CfgDbAccess::LEASE_DB);
|
||||
EXPECT_THROW(parser.parse(json_elements), DhcpConfigError);
|
||||
}
|
||||
|
||||
@ -549,7 +549,7 @@ TEST_F(DbAccessParserTest, incrementalChanges) {
|
||||
"name", "keatest",
|
||||
NULL};
|
||||
|
||||
TestDbAccessParser parser(DbAccessParser::LEASE_DB);
|
||||
TestDbAccessParser parser(CfgDbAccess::LEASE_DB);
|
||||
|
||||
// First configuration string should cause a representation of that string
|
||||
// to be held.
|
||||
@ -613,7 +613,7 @@ TEST_F(DbAccessParserTest, getDbAccessString) {
|
||||
ConstElementPtr json_elements = Element::fromJSON(json_config);
|
||||
EXPECT_TRUE(json_elements);
|
||||
|
||||
TestDbAccessParser parser(DbAccessParser::LEASE_DB);
|
||||
TestDbAccessParser parser(CfgDbAccess::LEASE_DB);
|
||||
EXPECT_NO_THROW(parser.parse(json_elements));
|
||||
|
||||
// Get the database access string
|
||||
@ -639,7 +639,7 @@ TEST_F(DbAccessParserTest, validReadOnly) {
|
||||
ConstElementPtr json_elements = Element::fromJSON(json_config);
|
||||
EXPECT_TRUE(json_elements);
|
||||
|
||||
TestDbAccessParser parser(DbAccessParser::LEASE_DB);
|
||||
TestDbAccessParser parser(CfgDbAccess::LEASE_DB);
|
||||
EXPECT_NO_THROW(parser.parse(json_elements));
|
||||
|
||||
checkAccessString("Valid readonly parameter",
|
||||
@ -661,9 +661,35 @@ TEST_F(DbAccessParserTest, invalidReadOnly) {
|
||||
ConstElementPtr json_elements = Element::fromJSON(json_config);
|
||||
EXPECT_TRUE(json_elements);
|
||||
|
||||
TestDbAccessParser parser(DbAccessParser::LEASE_DB);
|
||||
TestDbAccessParser parser(CfgDbAccess::LEASE_DB);
|
||||
EXPECT_THROW(parser.parse(json_elements), DhcpConfigError);
|
||||
}
|
||||
|
||||
// Check that multiple host storages are correctly parsed.
|
||||
TEST_F(DbAccessParserTest, multipleHost) {
|
||||
const char* config1[] = {"type", "mysql",
|
||||
"name", "keatest1",
|
||||
NULL};
|
||||
const char* config2[] = {"type", "mysql",
|
||||
"name", "keatest2",
|
||||
NULL};
|
||||
|
||||
string json_config1 = toJson(config1);
|
||||
string json_config2 = toJson(config2);
|
||||
ConstElementPtr json_elements1 = Element::fromJSON(json_config1);
|
||||
ConstElementPtr json_elements2 = Element::fromJSON(json_config2);
|
||||
|
||||
TestDbAccessParser parser1(2);
|
||||
TestDbAccessParser parser2(3);
|
||||
EXPECT_NO_THROW(parser1.parse(json_elements1));
|
||||
EXPECT_NO_THROW(parser2.parse(json_elements2));
|
||||
|
||||
checkAccessString("First config",
|
||||
parser1.getDbAccessParameters(),
|
||||
config1);
|
||||
checkAccessString("Second config",
|
||||
parser2.getDbAccessParameters(),
|
||||
config2);
|
||||
}
|
||||
|
||||
}; // Anonymous namespace
|
||||
|
178
src/lib/dhcpsrv/tests/host_data_source_factory_unittest.cc
Normal file
178
src/lib/dhcpsrv/tests/host_data_source_factory_unittest.cc
Normal file
@ -0,0 +1,178 @@
|
||||
// Copyright (C) 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
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <dhcpsrv/host_data_source_factory.h>
|
||||
#include <dhcpsrv/testutils/memory_host_data_source.h>
|
||||
#include <exceptions/exceptions.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
using namespace isc;
|
||||
using namespace isc::dhcp;
|
||||
using namespace isc::dhcp::test;
|
||||
|
||||
namespace {
|
||||
|
||||
// @brief Register memFactory
|
||||
bool registerFactory() {
|
||||
return (HostDataSourceFactory::registerFactory("mem", memFactory));
|
||||
}
|
||||
|
||||
// @brief Derive mem1 class
|
||||
class Mem1HostDataSource : public MemHostDataSource {
|
||||
public:
|
||||
virtual string getType() const {
|
||||
return ("mem1");
|
||||
}
|
||||
};
|
||||
|
||||
// @brief Factory of mem1
|
||||
BaseHostDataSource*
|
||||
mem1Factory(const DatabaseConnection::ParameterMap&) {
|
||||
return (new Mem1HostDataSource());
|
||||
}
|
||||
|
||||
// @brief Register mem1Factory
|
||||
bool registerFactory1() {
|
||||
return (HostDataSourceFactory::registerFactory("mem1", mem1Factory));
|
||||
}
|
||||
|
||||
// @brief Derive mem2 class
|
||||
class Mem2HostDataSource : public MemHostDataSource {
|
||||
public:
|
||||
virtual string getType() const {
|
||||
return ("mem2");
|
||||
}
|
||||
};
|
||||
|
||||
// @brief Factory of mem2
|
||||
BaseHostDataSource*
|
||||
mem2Factory(const DatabaseConnection::ParameterMap&) {
|
||||
return (new Mem2HostDataSource());
|
||||
}
|
||||
|
||||
// @brief Register mem2Factory
|
||||
bool registerFactory2() {
|
||||
return (HostDataSourceFactory::registerFactory("mem2", mem2Factory));
|
||||
}
|
||||
|
||||
// @brief Factory function returning 0
|
||||
BaseHostDataSource* factory0(const DatabaseConnection::ParameterMap&) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
// @brief Test fixture class
|
||||
class HostDataSourceFactoryTest : public ::testing::Test {
|
||||
private:
|
||||
// @brief Prepares the class for a test.
|
||||
virtual void SetUp() {
|
||||
}
|
||||
|
||||
// @brief Cleans up after the test.
|
||||
virtual void TearDown() {
|
||||
sources_.clear();
|
||||
HostDataSourceFactory::deregisterFactory("mem");
|
||||
HostDataSourceFactory::deregisterFactory("mem1");
|
||||
HostDataSourceFactory::deregisterFactory("mem2");
|
||||
}
|
||||
public:
|
||||
HostDataSourceList sources_;
|
||||
};
|
||||
|
||||
// Verify a factory can be registered and only once.
|
||||
TEST_F(HostDataSourceFactoryTest, registerFactory) {
|
||||
EXPECT_TRUE(registerFactory());
|
||||
|
||||
// Only once
|
||||
EXPECT_FALSE(registerFactory());
|
||||
}
|
||||
|
||||
// Verify a factory can be registered and deregistered
|
||||
TEST_F(HostDataSourceFactoryTest, deregisterFactory) {
|
||||
// Does not exist at the beginning
|
||||
EXPECT_FALSE(HostDataSourceFactory::deregisterFactory("mem"));
|
||||
|
||||
// Register and deregister
|
||||
EXPECT_TRUE(registerFactory());
|
||||
EXPECT_TRUE(HostDataSourceFactory::deregisterFactory("mem"));
|
||||
|
||||
// No longer exists
|
||||
EXPECT_FALSE(HostDataSourceFactory::deregisterFactory("mem"));
|
||||
}
|
||||
|
||||
// Verify a registered factory can be called
|
||||
TEST_F(HostDataSourceFactoryTest, add) {
|
||||
EXPECT_TRUE(registerFactory());
|
||||
EXPECT_NO_THROW(HostDataSourceFactory::add(sources_, "type=mem"));
|
||||
ASSERT_EQ(1, sources_.size());
|
||||
EXPECT_EQ("mem", sources_[0]->getType());
|
||||
}
|
||||
|
||||
// Verify that type is required
|
||||
TEST_F(HostDataSourceFactoryTest, notype) {
|
||||
EXPECT_THROW(HostDataSourceFactory::add(sources_, "tp=mem"),
|
||||
InvalidParameter);
|
||||
EXPECT_THROW(HostDataSourceFactory::add(sources_, "type=mem"),
|
||||
InvalidType);
|
||||
}
|
||||
|
||||
// Verify that factory must not return NULL
|
||||
TEST_F(HostDataSourceFactoryTest, null) {
|
||||
EXPECT_TRUE(HostDataSourceFactory::registerFactory("mem", factory0));
|
||||
EXPECT_THROW(HostDataSourceFactory::add(sources_, "type=mem"),
|
||||
Unexpected);
|
||||
}
|
||||
|
||||
// Verify del class method
|
||||
TEST_F(HostDataSourceFactoryTest, del) {
|
||||
// No sources at the beginning
|
||||
EXPECT_FALSE(HostDataSourceFactory::del(sources_, "mem"));
|
||||
|
||||
// Add mem
|
||||
EXPECT_TRUE(registerFactory());
|
||||
EXPECT_NO_THROW(HostDataSourceFactory::add(sources_, "type=mem"));
|
||||
ASSERT_EQ(1, sources_.size());
|
||||
|
||||
// Delete another
|
||||
EXPECT_FALSE(HostDataSourceFactory::del(sources_, "another"));
|
||||
|
||||
// Delete mem
|
||||
EXPECT_TRUE(HostDataSourceFactory::del(sources_, "mem"));
|
||||
|
||||
// No longer mem in sources
|
||||
EXPECT_FALSE(HostDataSourceFactory::del(sources_, "mem"));
|
||||
}
|
||||
|
||||
// Verify add and del class method on multiple backends
|
||||
TEST_F(HostDataSourceFactoryTest, multiple) {
|
||||
// Add foo twice
|
||||
EXPECT_TRUE(registerFactory1());
|
||||
EXPECT_NO_THROW(HostDataSourceFactory::add(sources_, "type=mem1"));
|
||||
EXPECT_NO_THROW(HostDataSourceFactory::add(sources_, "type=mem1"));
|
||||
|
||||
// Add mem2 once
|
||||
EXPECT_TRUE(registerFactory2());
|
||||
EXPECT_NO_THROW(HostDataSourceFactory::add(sources_, "type=mem2"));
|
||||
|
||||
// Delete them
|
||||
EXPECT_TRUE(HostDataSourceFactory::del(sources_, "mem1"));
|
||||
EXPECT_TRUE(HostDataSourceFactory::del(sources_, "mem2"));
|
||||
// Second instance of mem1
|
||||
EXPECT_TRUE(HostDataSourceFactory::del(sources_, "mem1"));
|
||||
|
||||
// No more sources
|
||||
EXPECT_EQ(0, sources_.size());
|
||||
EXPECT_FALSE(HostDataSourceFactory::del(sources_, "mem1"));
|
||||
EXPECT_FALSE(HostDataSourceFactory::del(sources_, "mem2"));
|
||||
}
|
||||
|
||||
}; // end of anonymous namespace
|
@ -1,4 +1,4 @@
|
||||
// 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
|
||||
@ -109,6 +109,10 @@ protected:
|
||||
/// from which it will be retrieved.
|
||||
void testGet4(BaseHostDataSource& data_source);
|
||||
|
||||
/// @brief This test verifies that it is possible to retrieve negative
|
||||
/// cached reservation with and only with get4Any,
|
||||
void testGet4Any();
|
||||
|
||||
/// @brief This test verifies that it is possible to retrieve an IPv6
|
||||
/// reservation for the particular host using HostMgr.
|
||||
///
|
||||
@ -116,6 +120,10 @@ protected:
|
||||
/// from which it will be retrieved.
|
||||
void testGet6(BaseHostDataSource& data_source);
|
||||
|
||||
/// @brief This test verifies that it is possible to retrieve negative
|
||||
/// cached reservation with and only with get6Any,
|
||||
void testGet6Any();
|
||||
|
||||
/// @brief This test verifies that it is possible to retrieve an IPv6
|
||||
/// prefix reservation for the particular host using HostMgr.
|
||||
///
|
||||
@ -210,8 +218,8 @@ HostMgrTest::testGetAll(BaseHostDataSource& data_source1,
|
||||
// If there non-matching HW address is specified, nothing should be
|
||||
// returned.
|
||||
hosts = HostMgr::instance().getAll(Host::IDENT_HWADDR,
|
||||
&hwaddrs_[1]->hwaddr_[0],
|
||||
hwaddrs_[1]->hwaddr_.size());
|
||||
&hwaddrs_[1]->hwaddr_[0],
|
||||
hwaddrs_[1]->hwaddr_.size());
|
||||
ASSERT_TRUE(hosts.empty());
|
||||
|
||||
// For the correct HW address, there should be two reservations.
|
||||
@ -225,7 +233,7 @@ HostMgrTest::testGetAll(BaseHostDataSource& data_source1,
|
||||
|
||||
// Look for the first reservation.
|
||||
bool found = false;
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
for (unsigned i = 0; i < 2; ++i) {
|
||||
if (hosts[0]->getIPv4Reservation() == IOAddress("192.0.2.5")) {
|
||||
ASSERT_EQ(1, hosts[0]->getIPv4SubnetID());
|
||||
found = true;
|
||||
@ -238,7 +246,7 @@ HostMgrTest::testGetAll(BaseHostDataSource& data_source1,
|
||||
|
||||
// Look for the second reservation.
|
||||
found = false;
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
for (unsigned i = 0; i < 2; ++i) {
|
||||
if (hosts[1]->getIPv4Reservation() == IOAddress("192.0.3.10")) {
|
||||
ASSERT_EQ(10, hosts[1]->getIPv4SubnetID());
|
||||
found = true;
|
||||
@ -297,6 +305,53 @@ HostMgrTest::testGet4(BaseHostDataSource& data_source) {
|
||||
EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
|
||||
}
|
||||
|
||||
void
|
||||
HostMgrTest::testGet4Any() {
|
||||
// Initially, no host should be present.
|
||||
ConstHostPtr host = HostMgr::instance().get4(SubnetID(1), Host::IDENT_DUID,
|
||||
&duids_[0]->getDuid()[0],
|
||||
duids_[0]->getDuid().size());
|
||||
ASSERT_FALSE(host);
|
||||
HostMgr::instance().get4Any(SubnetID(1), Host::IDENT_DUID,
|
||||
&duids_[0]->getDuid()[0],
|
||||
duids_[0]->getDuid().size());
|
||||
ASSERT_FALSE(host);
|
||||
|
||||
// Add new host to the database.
|
||||
HostPtr new_host(new Host(duids_[0]->toText(), "duid", SubnetID(1),
|
||||
SubnetID(0), IOAddress("192.0.2.5")));
|
||||
// Abuse of the server's configuration.
|
||||
getCfgHosts()->add(new_host);
|
||||
|
||||
CfgMgr::instance().commit();
|
||||
|
||||
// Retrieve the host from the database and expect that the parameters match.
|
||||
host = HostMgr::instance().get4(SubnetID(1), Host::IDENT_DUID,
|
||||
&duids_[0]->getDuid()[0],
|
||||
duids_[0]->getDuid().size());
|
||||
ASSERT_TRUE(host);
|
||||
EXPECT_EQ(1, host->getIPv4SubnetID());
|
||||
EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
|
||||
|
||||
// Set the negative cache flag on the host.
|
||||
new_host->setNegative(true);
|
||||
|
||||
// Get4 can't get it.
|
||||
host = HostMgr::instance().get4(SubnetID(1), Host::IDENT_DUID,
|
||||
&duids_[0]->getDuid()[0],
|
||||
duids_[0]->getDuid().size());
|
||||
EXPECT_FALSE(host);
|
||||
|
||||
// But Get4Any can.
|
||||
host = HostMgr::instance().get4Any(SubnetID(1), Host::IDENT_DUID,
|
||||
&duids_[0]->getDuid()[0],
|
||||
duids_[0]->getDuid().size());
|
||||
ASSERT_TRUE(host);
|
||||
EXPECT_EQ(1, host->getIPv4SubnetID());
|
||||
EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
|
||||
EXPECT_TRUE(host->getNegative());
|
||||
}
|
||||
|
||||
void
|
||||
HostMgrTest::testGet6(BaseHostDataSource& data_source) {
|
||||
// Initially, no host should be present.
|
||||
@ -313,10 +368,64 @@ HostMgrTest::testGet6(BaseHostDataSource& data_source) {
|
||||
&duids_[0]->getDuid()[0],
|
||||
duids_[0]->getDuid().size());
|
||||
ASSERT_TRUE(host);
|
||||
EXPECT_EQ(2, host->getIPv6SubnetID());
|
||||
EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
|
||||
IOAddress("2001:db8:1::1"))));
|
||||
}
|
||||
|
||||
void
|
||||
HostMgrTest::testGet6Any() {
|
||||
// Initially, no host should be present.
|
||||
ConstHostPtr host = HostMgr::instance().get6(SubnetID(2),
|
||||
Host::IDENT_HWADDR,
|
||||
&hwaddrs_[0]->hwaddr_[0],
|
||||
hwaddrs_[0]->hwaddr_.size());
|
||||
ASSERT_FALSE(host);
|
||||
host = HostMgr::instance().get6Any(SubnetID(2), Host::IDENT_HWADDR,
|
||||
&hwaddrs_[0]->hwaddr_[0],
|
||||
hwaddrs_[0]->hwaddr_.size());
|
||||
ASSERT_FALSE(host);
|
||||
|
||||
// Add new host to the database.
|
||||
HostPtr new_host(new Host(hwaddrs_[0]->toText(false), "hw-address",
|
||||
SubnetID(1), SubnetID(2),
|
||||
IOAddress::IPV4_ZERO_ADDRESS()));
|
||||
new_host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
|
||||
IOAddress("2001:db8:1::1"), 128));
|
||||
// Abuse of the server's configuration.
|
||||
getCfgHosts()->add(new_host);
|
||||
|
||||
CfgMgr::instance().commit();
|
||||
|
||||
// Retrieve the host from the database and expect that the parameters match.
|
||||
host = HostMgr::instance().get6(SubnetID(2), Host::IDENT_HWADDR,
|
||||
&hwaddrs_[0]->hwaddr_[0],
|
||||
hwaddrs_[0]->hwaddr_.size());
|
||||
ASSERT_TRUE(host);
|
||||
EXPECT_EQ(2, host->getIPv6SubnetID());
|
||||
EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
|
||||
IOAddress("2001:db8:1::1"))));
|
||||
|
||||
// Set the negative cache flag on the host.
|
||||
new_host->setNegative(true);
|
||||
|
||||
// Get6 can't get it.
|
||||
host = HostMgr::instance().get6(SubnetID(2), Host::IDENT_HWADDR,
|
||||
&hwaddrs_[0]->hwaddr_[0],
|
||||
hwaddrs_[0]->hwaddr_.size());
|
||||
EXPECT_FALSE(host);
|
||||
|
||||
// But Get4Any can.
|
||||
host = HostMgr::instance().get6Any(SubnetID(2), Host::IDENT_HWADDR,
|
||||
&hwaddrs_[0]->hwaddr_[0],
|
||||
hwaddrs_[0]->hwaddr_.size());
|
||||
ASSERT_TRUE(host);
|
||||
EXPECT_EQ(2, host->getIPv6SubnetID());
|
||||
EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
|
||||
IOAddress("2001:db8:1::1"))));
|
||||
EXPECT_TRUE(host->getNegative());
|
||||
}
|
||||
|
||||
void
|
||||
HostMgrTest::testGet6ByPrefix(BaseHostDataSource& data_source1,
|
||||
BaseHostDataSource& data_source2) {
|
||||
@ -375,6 +484,11 @@ TEST_F(HostMgrTest, get4) {
|
||||
testGet4(*getCfgHosts());
|
||||
}
|
||||
|
||||
// This test verifies handling of negative caching by get4/get4Any.
|
||||
TEST_F(HostMgrTest, get4Any) {
|
||||
testGet4Any();
|
||||
}
|
||||
|
||||
// This test verifies that it is possible to retrieve IPv6 reservations for
|
||||
// the particular host using HostMgr. The reservation is specified in the
|
||||
// server's configuration.
|
||||
@ -382,6 +496,11 @@ TEST_F(HostMgrTest, get6) {
|
||||
testGet6(*getCfgHosts());
|
||||
}
|
||||
|
||||
// This test verifies handling of negative caching by get4/get4Any.
|
||||
TEST_F(HostMgrTest, get6Any) {
|
||||
testGet6Any();
|
||||
}
|
||||
|
||||
// This test verifies that it is possible to retrieve the reservation of the
|
||||
// particular IPv6 prefix using HostMgr.
|
||||
TEST_F(HostMgrTest, get6ByPrefix) {
|
||||
@ -425,7 +544,7 @@ MySQLHostMgrTest::SetUp() {
|
||||
|
||||
// Connect to the database
|
||||
try {
|
||||
HostMgr::create(test::validMySQLConnectionString());
|
||||
HostMgr::addSource(test::validMySQLConnectionString());
|
||||
} catch (...) {
|
||||
std::cerr << "*** ERROR: unable to open database. The test\n"
|
||||
"*** environment is broken and must be fixed before\n"
|
||||
@ -438,8 +557,8 @@ MySQLHostMgrTest::SetUp() {
|
||||
|
||||
void
|
||||
MySQLHostMgrTest::TearDown() {
|
||||
HostDataSourceFactory::getHostDataSourcePtr()->rollback();
|
||||
HostDataSourceFactory::destroy();
|
||||
HostMgr::instance().getHostDataSource()->rollback();
|
||||
HostMgr::delSource("mysql");
|
||||
test::destroyMySQLSchema();
|
||||
}
|
||||
|
||||
@ -502,7 +621,7 @@ PostgreSQLHostMgrTest::SetUp() {
|
||||
|
||||
// Connect to the database
|
||||
try {
|
||||
HostMgr::create(test::validPgSQLConnectionString());
|
||||
HostMgr::addSource(test::validPgSQLConnectionString());
|
||||
} catch (...) {
|
||||
std::cerr << "*** ERROR: unable to open database. The test\n"
|
||||
"*** environment is broken and must be fixed before\n"
|
||||
@ -515,8 +634,8 @@ PostgreSQLHostMgrTest::SetUp() {
|
||||
|
||||
void
|
||||
PostgreSQLHostMgrTest::TearDown() {
|
||||
HostDataSourceFactory::getHostDataSourcePtr()->rollback();
|
||||
HostDataSourceFactory::destroy();
|
||||
HostMgr::instance().getHostDataSource()->rollback();
|
||||
HostMgr::delSource("postgresql");
|
||||
test::destroyPgSQLSchema();
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// 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
|
||||
@ -669,6 +669,7 @@ TEST_F(HostTest, setValues) {
|
||||
ASSERT_EQ("192.0.2.3", host->getIPv4Reservation().toText());
|
||||
ASSERT_EQ("some-host.example.org", host->getHostname());
|
||||
ASSERT_FALSE(host->getContext());
|
||||
ASSERT_FALSE(host->getNegative());
|
||||
|
||||
host->setIPv4SubnetID(SubnetID(123));
|
||||
host->setIPv6SubnetID(SubnetID(234));
|
||||
@ -679,6 +680,7 @@ TEST_F(HostTest, setValues) {
|
||||
host->setBootFileName("bootfile.efi");
|
||||
std::string user_context = "{ \"foo\": \"bar\" }";
|
||||
host->setContext(Element::fromJSON(user_context));
|
||||
host->setNegative(true);
|
||||
|
||||
EXPECT_EQ(123, host->getIPv4SubnetID());
|
||||
EXPECT_EQ(234, host->getIPv6SubnetID());
|
||||
@ -689,6 +691,7 @@ TEST_F(HostTest, setValues) {
|
||||
EXPECT_EQ("bootfile.efi", host->getBootFileName());
|
||||
ASSERT_TRUE(host->getContext());
|
||||
EXPECT_EQ(user_context, host->getContext()->str());
|
||||
EXPECT_TRUE(host->getNegative());
|
||||
|
||||
// Remove IPv4 reservation.
|
||||
host->removeIPv4Reservation();
|
||||
@ -981,6 +984,7 @@ TEST_F(HostTest, toText) {
|
||||
host->setHostname("");
|
||||
host->removeIPv4Reservation();
|
||||
host->setIPv4SubnetID(0);
|
||||
host->setNegative(true);
|
||||
|
||||
EXPECT_EQ("hwaddr=010203040506 ipv6_subnet_id=2"
|
||||
" hostname=(empty) ipv4_reservation=(no)"
|
||||
@ -990,7 +994,8 @@ TEST_F(HostTest, toText) {
|
||||
" ipv6_reservation0=2001:db8:1::cafe"
|
||||
" ipv6_reservation1=2001:db8:1::1"
|
||||
" ipv6_reservation2=2001:db8:1:1::/64"
|
||||
" ipv6_reservation3=2001:db8:1:2::/64",
|
||||
" ipv6_reservation3=2001:db8:1:2::/64"
|
||||
" negative cached",
|
||||
host->toText());
|
||||
|
||||
// Create host identified by DUID, instead of HWADDR, with a very
|
||||
@ -1139,6 +1144,8 @@ TEST_F(HostTest, unparse) {
|
||||
// Add some classes.
|
||||
host->addClientClass4("modem");
|
||||
host->addClientClass4("router");
|
||||
// Set invisible negative cache.
|
||||
host->setNegative(true);
|
||||
|
||||
EXPECT_EQ("{ "
|
||||
"\"boot-file-name\": \"\", "
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2015-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
|
||||
@ -12,9 +12,10 @@
|
||||
#include <dhcpsrv/host.h>
|
||||
#include <dhcpsrv/mysql_connection.h>
|
||||
#include <dhcpsrv/mysql_host_data_source.h>
|
||||
#include <dhcpsrv/tests/generic_host_data_source_unittest.h>
|
||||
#include <dhcpsrv/testutils/generic_host_data_source_unittest.h>
|
||||
#include <dhcpsrv/testutils/mysql_schema.h>
|
||||
#include <dhcpsrv/testutils/host_data_source_utils.h>
|
||||
#include <dhcpsrv/host_mgr.h>
|
||||
#include <dhcpsrv/host_data_source_factory.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
@ -47,7 +48,8 @@ public:
|
||||
|
||||
// Connect to the database
|
||||
try {
|
||||
HostDataSourceFactory::create(validMySQLConnectionString());
|
||||
HostMgr::create();
|
||||
HostMgr::addSource(validMySQLConnectionString());
|
||||
} catch (...) {
|
||||
std::cerr << "*** ERROR: unable to open database. The test\n"
|
||||
"*** environment is broken and must be fixed before\n"
|
||||
@ -57,7 +59,7 @@ public:
|
||||
throw;
|
||||
}
|
||||
|
||||
hdsptr_ = HostDataSourceFactory::getHostDataSourcePtr();
|
||||
hdsptr_ = HostMgr::instance().getHostDataSource();
|
||||
}
|
||||
|
||||
/// @brief Destructor
|
||||
@ -70,7 +72,7 @@ public:
|
||||
} catch (...) {
|
||||
// Rollback may fail if backend is in read only mode. That's ok.
|
||||
}
|
||||
HostDataSourceFactory::destroy();
|
||||
HostMgr::delAllSources();
|
||||
hdsptr_.reset();
|
||||
destroyMySQLSchema();
|
||||
}
|
||||
@ -83,9 +85,9 @@ public:
|
||||
/// Parameter is ignored for MySQL backend as the v4 and v6 leases share
|
||||
/// the same database.
|
||||
void reopen(Universe) {
|
||||
HostDataSourceFactory::destroy();
|
||||
HostDataSourceFactory::create(validMySQLConnectionString());
|
||||
hdsptr_ = HostDataSourceFactory::getHostDataSourcePtr();
|
||||
HostMgr::create();
|
||||
HostMgr::addSource(validMySQLConnectionString());
|
||||
hdsptr_ = HostMgr::instance().getHostDataSource();
|
||||
}
|
||||
|
||||
/// @brief returns number of rows in a table
|
||||
@ -149,9 +151,9 @@ TEST(MySqlHostDataSource, OpenDatabase) {
|
||||
// Check that lease manager open the database opens correctly and tidy up.
|
||||
// If it fails, print the error message.
|
||||
try {
|
||||
HostDataSourceFactory::create(validMySQLConnectionString());
|
||||
EXPECT_NO_THROW((void) HostDataSourceFactory::getHostDataSourcePtr());
|
||||
HostDataSourceFactory::destroy();
|
||||
HostMgr::create();
|
||||
EXPECT_NO_THROW(HostMgr::addSource(validMySQLConnectionString()));
|
||||
HostMgr::delSource("mysql");
|
||||
} catch (const isc::Exception& ex) {
|
||||
FAIL() << "*** ERROR: unable to open database, reason:\n"
|
||||
<< " " << ex.what() << "\n"
|
||||
@ -164,9 +166,9 @@ TEST(MySqlHostDataSource, OpenDatabase) {
|
||||
try {
|
||||
string connection_string = validMySQLConnectionString() + string(" ") +
|
||||
string(VALID_TIMEOUT);
|
||||
HostDataSourceFactory::create(connection_string);
|
||||
EXPECT_NO_THROW((void) HostDataSourceFactory::getHostDataSourcePtr());
|
||||
HostDataSourceFactory::destroy();
|
||||
HostMgr::create();
|
||||
EXPECT_NO_THROW(HostMgr::addSource(connection_string));
|
||||
HostMgr::delSource("mysql");
|
||||
} catch (const isc::Exception& ex) {
|
||||
FAIL() << "*** ERROR: unable to open database, reason:\n"
|
||||
<< " " << ex.what() << "\n"
|
||||
@ -176,43 +178,43 @@ TEST(MySqlHostDataSource, OpenDatabase) {
|
||||
|
||||
// Check that attempting to get an instance of the lease manager when
|
||||
// none is set throws an exception.
|
||||
EXPECT_FALSE(HostDataSourceFactory::getHostDataSourcePtr());
|
||||
EXPECT_FALSE(HostMgr::instance().getHostDataSource());
|
||||
|
||||
// Check that wrong specification of backend throws an exception.
|
||||
// (This is really a check on LeaseMgrFactory, but is convenient to
|
||||
// perform here.)
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(
|
||||
NULL, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
|
||||
InvalidParameter);
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(
|
||||
INVALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)),
|
||||
InvalidType);
|
||||
|
||||
// Check that invalid login data causes an exception.
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(
|
||||
MYSQL_VALID_TYPE, INVALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)),
|
||||
DbOpenError);
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(
|
||||
MYSQL_VALID_TYPE, VALID_NAME, INVALID_HOST, VALID_USER, VALID_PASSWORD)),
|
||||
DbOpenError);
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(
|
||||
MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
|
||||
DbOpenError);
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(
|
||||
MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, INVALID_PASSWORD)),
|
||||
DbOpenError);
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(
|
||||
MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD, INVALID_TIMEOUT_1)),
|
||||
DbInvalidTimeout);
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(
|
||||
MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD, INVALID_TIMEOUT_2)),
|
||||
DbInvalidTimeout);
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(
|
||||
MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD,
|
||||
VALID_TIMEOUT, INVALID_READONLY_DB)), DbInvalidReadOnly);
|
||||
|
||||
// Check for missing parameters
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(
|
||||
MYSQL_VALID_TYPE, NULL, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
|
||||
NoDatabaseName);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2016-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
|
||||
@ -12,9 +12,10 @@
|
||||
#include <dhcpsrv/host.h>
|
||||
#include <dhcpsrv/pgsql_connection.h>
|
||||
#include <dhcpsrv/pgsql_host_data_source.h>
|
||||
#include <dhcpsrv/tests/generic_host_data_source_unittest.h>
|
||||
#include <dhcpsrv/testutils/generic_host_data_source_unittest.h>
|
||||
#include <dhcpsrv/testutils/pgsql_schema.h>
|
||||
#include <dhcpsrv/testutils/host_data_source_utils.h>
|
||||
#include <dhcpsrv/host_mgr.h>
|
||||
#include <dhcpsrv/host_data_source_factory.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
@ -47,7 +48,8 @@ public:
|
||||
|
||||
// Connect to the database
|
||||
try {
|
||||
HostDataSourceFactory::create(validPgSQLConnectionString());
|
||||
HostMgr::create();
|
||||
HostMgr::addSource(validPgSQLConnectionString());
|
||||
} catch (...) {
|
||||
std::cerr << "*** ERROR: unable to open database. The test\n"
|
||||
"*** environment is broken and must be fixed before\n"
|
||||
@ -57,7 +59,7 @@ public:
|
||||
throw;
|
||||
}
|
||||
|
||||
hdsptr_ = HostDataSourceFactory::getHostDataSourcePtr();
|
||||
hdsptr_ = HostMgr::instance().getHostDataSource();
|
||||
}
|
||||
|
||||
/// @brief Destructor
|
||||
@ -71,7 +73,7 @@ public:
|
||||
} catch (...) {
|
||||
// Rollback may fail if backend is in read only mode. That's ok.
|
||||
}
|
||||
HostDataSourceFactory::destroy();
|
||||
HostMgr::delAllSources();
|
||||
hdsptr_.reset();
|
||||
destroyPgSQLSchema();
|
||||
}
|
||||
@ -84,9 +86,9 @@ public:
|
||||
/// Parameter is ignored for PostgreSQL backend as the v4 and v6 leases
|
||||
/// share the same database.
|
||||
void reopen(Universe) {
|
||||
HostDataSourceFactory::destroy();
|
||||
HostDataSourceFactory::create(validPgSQLConnectionString());
|
||||
hdsptr_ = HostDataSourceFactory::getHostDataSourcePtr();
|
||||
HostMgr::create();
|
||||
HostMgr::addSource(validPgSQLConnectionString());
|
||||
hdsptr_ = HostMgr::instance().getHostDataSource();
|
||||
}
|
||||
|
||||
/// @brief returns number of rows in a table
|
||||
@ -149,9 +151,9 @@ TEST(PgSqlHostDataSource, OpenDatabase) {
|
||||
// Check that lease manager open the database opens correctly and tidy up.
|
||||
// If it fails, print the error message.
|
||||
try {
|
||||
HostDataSourceFactory::create(validPgSQLConnectionString());
|
||||
EXPECT_NO_THROW((void) HostDataSourceFactory::getHostDataSourcePtr());
|
||||
HostDataSourceFactory::destroy();
|
||||
HostMgr::create();
|
||||
EXPECT_NO_THROW(HostMgr::addSource(validPgSQLConnectionString()));
|
||||
HostMgr::delSource("postgresql");
|
||||
} catch (const isc::Exception& ex) {
|
||||
FAIL() << "*** ERROR: unable to open database, reason:\n"
|
||||
<< " " << ex.what() << "\n"
|
||||
@ -164,9 +166,8 @@ TEST(PgSqlHostDataSource, OpenDatabase) {
|
||||
try {
|
||||
string connection_string = validPgSQLConnectionString() + string(" ") +
|
||||
string(VALID_TIMEOUT);
|
||||
HostDataSourceFactory::create(connection_string);
|
||||
EXPECT_NO_THROW((void) HostDataSourceFactory::getHostDataSourcePtr());
|
||||
HostDataSourceFactory::destroy();
|
||||
EXPECT_NO_THROW(HostMgr::addSource(connection_string));
|
||||
HostMgr::delSource("postgresql");
|
||||
} catch (const isc::Exception& ex) {
|
||||
FAIL() << "*** ERROR: unable to open database, reason:\n"
|
||||
<< " " << ex.what() << "\n"
|
||||
@ -176,40 +177,40 @@ TEST(PgSqlHostDataSource, OpenDatabase) {
|
||||
|
||||
// Check that attempting to get an instance of the lease manager when
|
||||
// none is set throws an exception.
|
||||
EXPECT_FALSE(HostDataSourceFactory::getHostDataSourcePtr());
|
||||
EXPECT_FALSE(HostMgr::instance().getHostDataSource());
|
||||
|
||||
// Check that wrong specification of backend throws an exception.
|
||||
// (This is really a check on LeaseMgrFactory, but is convenient to
|
||||
// perform here.)
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(
|
||||
NULL, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
|
||||
InvalidParameter);
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(
|
||||
INVALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)),
|
||||
InvalidType);
|
||||
|
||||
// Check that invalid login data causes an exception.
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(
|
||||
PGSQL_VALID_TYPE, INVALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)),
|
||||
DbOpenError);
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(
|
||||
PGSQL_VALID_TYPE, VALID_NAME, INVALID_HOST, VALID_USER, VALID_PASSWORD)),
|
||||
DbOpenError);
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(
|
||||
PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
|
||||
DbOpenError);
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(
|
||||
PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, INVALID_PASSWORD)),
|
||||
DbOpenError);
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(
|
||||
PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD, INVALID_TIMEOUT_1)),
|
||||
DbInvalidTimeout);
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(
|
||||
PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD, INVALID_TIMEOUT_2)),
|
||||
DbInvalidTimeout);
|
||||
|
||||
// Check for missing parameters
|
||||
EXPECT_THROW(HostDataSourceFactory::create(connectionString(
|
||||
EXPECT_THROW(HostMgr::addSource(connectionString(
|
||||
PGSQL_VALID_TYPE, NULL, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
|
||||
NoDatabaseName);
|
||||
|
||||
|
@ -15,6 +15,9 @@ noinst_LTLIBRARIES = libdhcpsrvtest.la
|
||||
libdhcpsrvtest_la_SOURCES = config_result_check.cc config_result_check.h
|
||||
libdhcpsrvtest_la_SOURCES += dhcp4o6_test_ipc.cc dhcp4o6_test_ipc.h
|
||||
libdhcpsrvtest_la_SOURCES += host_data_source_utils.cc host_data_source_utils.h
|
||||
libdhcpsrvtest_la_SOURCES += memory_host_data_source.cc memory_host_data_source.h
|
||||
libdhcpsrvtest_la_SOURCES += generic_host_data_source_unittest.cc generic_host_data_source_unittest.h
|
||||
|
||||
libdhcpsrvtest_la_SOURCES += schema.cc schema.h
|
||||
libdhcpsrvtest_la_SOURCES += lease_file_io.cc lease_file_io.h
|
||||
|
||||
|
@ -14,15 +14,16 @@
|
||||
#include <dhcp/option_string.h>
|
||||
#include <dhcp/option_vendor.h>
|
||||
#include <dhcpsrv/database_connection.h>
|
||||
#include <dhcpsrv/db_exceptions.h>
|
||||
#include <dhcpsrv/host_mgr.h>
|
||||
#include <dhcpsrv/host_data_source_factory.h>
|
||||
#include <dhcpsrv/tests/generic_host_data_source_unittest.h>
|
||||
#include <dhcpsrv/tests/test_utils.h>
|
||||
#include <dhcpsrv/testutils/generic_host_data_source_unittest.h>
|
||||
#include <dhcpsrv/testutils/schema.h>
|
||||
#include <dhcpsrv/testutils/host_data_source_utils.h>
|
||||
#include <util/buffer.h>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <dhcpsrv/testutils/host_data_source_utils.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <util/buffer.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
@ -195,7 +196,9 @@ GenericHostDataSourceTest::testReadOnlyDatabase(const char* valid_db_type) {
|
||||
// insert some data to the database.
|
||||
HostPtr host = HostDataSourceUtils::initializeHost6("2001:db8::1", Host::IDENT_DUID, false);
|
||||
ASSERT_TRUE(host);
|
||||
ASSERT_NO_THROW(hdsptr_->add(host));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// Subnet id will be used in queries to the database.
|
||||
SubnetID subnet_id = host->getIPv6SubnetID();
|
||||
@ -210,12 +213,12 @@ GenericHostDataSourceTest::testReadOnlyDatabase(const char* valid_db_type) {
|
||||
|
||||
// Close the database connection and reopen in "read-only" mode as
|
||||
// specified by the "VALID_READONLY_DB" parameter.
|
||||
HostDataSourceFactory::destroy();
|
||||
HostDataSourceFactory::create(connectionString(
|
||||
HostMgr::create();
|
||||
HostMgr::addSource(connectionString(
|
||||
valid_db_type, VALID_NAME, VALID_HOST, VALID_READONLY_USER,
|
||||
VALID_PASSWORD, VALID_READONLY_DB));
|
||||
|
||||
hdsptr_ = HostDataSourceFactory::getHostDataSourcePtr();
|
||||
hdsptr_ = HostMgr::instance().getHostDataSource();
|
||||
|
||||
// Check that an attempt to insert new host would result in
|
||||
// exception.
|
||||
@ -244,7 +247,9 @@ GenericHostDataSourceTest::testBasic4(const Host::IdentifierType& id) {
|
||||
SubnetID subnet = host->getIPv4SubnetID();
|
||||
|
||||
// Try to add it to the host data source.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// This should not return anything
|
||||
ConstHostPtr from_hds = hdsptr_->get4(subnet, IOAddress("10.10.10.10"));
|
||||
@ -270,10 +275,15 @@ GenericHostDataSourceTest::testGetByIPv4(const Host::IdentifierType& id) {
|
||||
HostPtr host4 = HostDataSourceUtils::initializeHost4("192.0.2.4", id);
|
||||
|
||||
// ... and add them to the data source.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host1));
|
||||
ASSERT_NO_THROW(hdsptr_->add(host2));
|
||||
ASSERT_NO_THROW(hdsptr_->add(host3));
|
||||
ASSERT_NO_THROW(hdsptr_->add(host4));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host1));
|
||||
EXPECT_TRUE(added);
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host2));
|
||||
EXPECT_TRUE(added);
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host3));
|
||||
EXPECT_TRUE(added);
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host4));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
SubnetID subnet1 = host1->getIPv4SubnetID();
|
||||
SubnetID subnet2 = host2->getIPv4SubnetID();
|
||||
@ -316,8 +326,11 @@ GenericHostDataSourceTest::testGet4ByIdentifier(
|
||||
ASSERT_FALSE(host1->getIdentifier() == host2->getIdentifier());
|
||||
|
||||
// Try to add both of them to the host data source.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host1));
|
||||
ASSERT_NO_THROW(hdsptr_->add(host2));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host1));
|
||||
EXPECT_TRUE(added);
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host2));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
SubnetID subnet1 = host1->getIPv4SubnetID();
|
||||
SubnetID subnet2 = host2->getIPv4SubnetID();
|
||||
@ -348,7 +361,9 @@ GenericHostDataSourceTest::testHWAddrNotClientId() {
|
||||
ASSERT_FALSE(host->getDuid());
|
||||
|
||||
// Try to add it to the host data source.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
SubnetID subnet = host->getIPv4SubnetID();
|
||||
|
||||
@ -380,7 +395,9 @@ GenericHostDataSourceTest::testClientIdNotHWAddr() {
|
||||
ASSERT_TRUE(host->getDuid());
|
||||
|
||||
// Try to add it to the host data source.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
SubnetID subnet = host->getIPv4SubnetID();
|
||||
|
||||
@ -433,7 +450,9 @@ GenericHostDataSourceTest::testHostname(std::string name, int num) {
|
||||
for (vector<HostPtr>::const_iterator it = hosts.begin(); it != hosts.end();
|
||||
++it) {
|
||||
// Try to add both of the to the host data source.
|
||||
ASSERT_NO_THROW(hdsptr_->add(*it));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(*it));
|
||||
EXPECT_TRUE(added);
|
||||
}
|
||||
|
||||
// And finally retrieve them one by one and check
|
||||
@ -462,7 +481,9 @@ GenericHostDataSourceTest::testUserContext(ConstElementPtr user_context) {
|
||||
SubnetID subnet = host->getIPv4SubnetID();
|
||||
|
||||
// Try to add it to the host data source.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// Retrieve it.
|
||||
ConstHostPtr from_hds = hdsptr_->get4(subnet, IOAddress("192.0.2.1"));
|
||||
@ -479,7 +500,8 @@ GenericHostDataSourceTest::testUserContext(ConstElementPtr user_context) {
|
||||
host->setHostname("foo.example.com");
|
||||
subnet = host->getIPv6SubnetID();
|
||||
|
||||
ASSERT_NO_THROW(hdsptr_->add(host));
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
from_hds = hdsptr_->get6(subnet, Host::IDENT_HWADDR,
|
||||
&host->getIdentifier()[0],
|
||||
@ -502,7 +524,9 @@ GenericHostDataSourceTest::testMultipleSubnets(int subnets,
|
||||
host->setIPv4SubnetID(i + 1000);
|
||||
|
||||
// Check that the same host can have reservations in multiple subnets.
|
||||
EXPECT_NO_THROW(hdsptr_->add(host));
|
||||
bool added = false;
|
||||
EXPECT_NO_THROW(added = hdsptr_->add(host));
|
||||
EXPECT_TRUE(added);
|
||||
}
|
||||
|
||||
// Now check that the reservations can be retrieved by IPv4 address from
|
||||
@ -576,8 +600,11 @@ GenericHostDataSourceTest::testGet6ByHWAddr() {
|
||||
HostDataSourceUtils::compareHwaddrs(host1, host2, false);
|
||||
|
||||
// Try to add both of them to the host data source.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host1));
|
||||
ASSERT_NO_THROW(hdsptr_->add(host2));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host1));
|
||||
EXPECT_TRUE(added);
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host2));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
SubnetID subnet1 = host1->getIPv6SubnetID();
|
||||
SubnetID subnet2 = host2->getIPv6SubnetID();
|
||||
@ -613,8 +640,11 @@ GenericHostDataSourceTest::testGet6ByClientId() {
|
||||
HostDataSourceUtils::compareDuids(host1, host2, false);
|
||||
|
||||
// Try to add both of them to the host data source.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host1));
|
||||
ASSERT_NO_THROW(hdsptr_->add(host2));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host1));
|
||||
EXPECT_TRUE(added);
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host2));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
SubnetID subnet1 = host1->getIPv6SubnetID();
|
||||
SubnetID subnet2 = host2->getIPv6SubnetID();
|
||||
@ -650,7 +680,9 @@ GenericHostDataSourceTest::testSubnetId6(int subnets, Host::IdentifierType id) {
|
||||
host->setIPv6SubnetID(i + 1000);
|
||||
|
||||
// Check that the same host can have reservations in multiple subnets.
|
||||
EXPECT_NO_THROW(hdsptr_->add(host));
|
||||
bool added = false;
|
||||
EXPECT_NO_THROW(added = hdsptr_->add(host));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// Increase address to make sure we don't assign the same address
|
||||
// in different subnets.
|
||||
@ -698,10 +730,15 @@ GenericHostDataSourceTest::testGetByIPv6(Host::IdentifierType id, bool prefix) {
|
||||
HostPtr host4 = HostDataSourceUtils::initializeHost6("2001:db8::4", id, prefix);
|
||||
|
||||
// ... and add them to the data source.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host1));
|
||||
ASSERT_NO_THROW(hdsptr_->add(host2));
|
||||
ASSERT_NO_THROW(hdsptr_->add(host3));
|
||||
ASSERT_NO_THROW(hdsptr_->add(host4));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host1));
|
||||
EXPECT_TRUE(added);
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host2));
|
||||
EXPECT_TRUE(added);
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host3));
|
||||
EXPECT_TRUE(added);
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host4));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// Are we talking about addresses or prefixes?
|
||||
uint8_t len = prefix ? 64 : 128;
|
||||
@ -741,10 +778,15 @@ GenericHostDataSourceTest::testGetBySubnetIPv6() {
|
||||
HostPtr host4 = HostDataSourceUtils::initializeHost6("2001:db8:4::", Host::IDENT_DUID, true);
|
||||
|
||||
// ... and add them to the data source.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host1));
|
||||
ASSERT_NO_THROW(hdsptr_->add(host2));
|
||||
ASSERT_NO_THROW(hdsptr_->add(host3));
|
||||
ASSERT_NO_THROW(hdsptr_->add(host4));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host1));
|
||||
EXPECT_TRUE(added);
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host2));
|
||||
EXPECT_TRUE(added);
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host3));
|
||||
EXPECT_TRUE(added);
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host4));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// And then try to retrieve them back.
|
||||
ConstHostPtr from_hds1 = hdsptr_->get6(host1->getIPv6SubnetID(), IOAddress("2001:db8:1::"));
|
||||
@ -774,7 +816,9 @@ GenericHostDataSourceTest::testAddDuplicate6WithSameDUID() {
|
||||
HostPtr host = HostDataSourceUtils::initializeHost6("2001:db8::1", Host::IDENT_DUID, true);
|
||||
|
||||
// Add this reservation once.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// Then try to add it again, it should throw an exception.
|
||||
ASSERT_THROW(hdsptr_->add(host), DuplicateEntry);
|
||||
@ -789,7 +833,9 @@ GenericHostDataSourceTest::testAddDuplicate6WithSameHWAddr() {
|
||||
HostPtr host = HostDataSourceUtils::initializeHost6("2001:db8::1", Host::IDENT_HWADDR, true);
|
||||
|
||||
// Add this reservation once.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// Then try to add it again, it should throw an exception.
|
||||
ASSERT_THROW(hdsptr_->add(host), DuplicateEntry);
|
||||
@ -804,7 +850,9 @@ GenericHostDataSourceTest::testAddDuplicate4() {
|
||||
HostPtr host = HostDataSourceUtils::initializeHost4("192.0.2.1", Host::IDENT_DUID);
|
||||
|
||||
// Add this reservation once.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// Then try to add it again, it should throw an exception.
|
||||
ASSERT_THROW(hdsptr_->add(host), DuplicateEntry);
|
||||
@ -818,7 +866,8 @@ GenericHostDataSourceTest::testAddDuplicate4() {
|
||||
// Modify address to avoid its duplication and make sure
|
||||
// we can now add the host.
|
||||
ASSERT_NO_THROW(host->setIPv4Reservation(IOAddress("192.0.2.3")));
|
||||
EXPECT_NO_THROW(hdsptr_->add(host));
|
||||
EXPECT_NO_THROW(added = hdsptr_->add(host));
|
||||
EXPECT_TRUE(added);
|
||||
}
|
||||
|
||||
void
|
||||
@ -834,7 +883,9 @@ GenericHostDataSourceTest::testAddr6AndPrefix() {
|
||||
host->addReservation(resv);
|
||||
|
||||
// Add this reservation
|
||||
ASSERT_NO_THROW(hdsptr_->add(host));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// Get this host by DUID
|
||||
ConstHostPtr from_hds =
|
||||
@ -868,7 +919,9 @@ GenericHostDataSourceTest::testMultipleReservations() {
|
||||
host->addReservation(resv3);
|
||||
host->addReservation(resv4);
|
||||
|
||||
ASSERT_NO_THROW(hdsptr_->add(host));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
ConstHostPtr from_hds = hdsptr_->get6(IOAddress("2001:db8::1"), len);
|
||||
|
||||
@ -915,7 +968,9 @@ void GenericHostDataSourceTest::testOptionsReservations4(const bool formatted,
|
||||
// Add a bunch of DHCPv4 and DHCPv6 options for the host.
|
||||
ASSERT_NO_THROW(addTestOptions(host, formatted, DHCP4_ONLY, user_context));
|
||||
// Insert host and the options into respective tables.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host));
|
||||
EXPECT_TRUE(added);
|
||||
// Subnet id will be used in queries to the database.
|
||||
SubnetID subnet_id = host->getIPv4SubnetID();
|
||||
|
||||
@ -943,7 +998,9 @@ void GenericHostDataSourceTest::testOptionsReservations6(const bool formatted,
|
||||
// Add a bunch of DHCPv4 and DHCPv6 options for the host.
|
||||
ASSERT_NO_THROW(addTestOptions(host, formatted, DHCP6_ONLY, user_context));
|
||||
// Insert host, options and IPv6 reservations into respective tables.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host));
|
||||
EXPECT_TRUE(added);
|
||||
// Subnet id will be used in queries to the database.
|
||||
SubnetID subnet_id = host->getIPv6SubnetID();
|
||||
|
||||
@ -965,7 +1022,9 @@ GenericHostDataSourceTest::testOptionsReservations46(const bool formatted) {
|
||||
// Add a bunch of DHCPv4 and DHCPv6 options for the host.
|
||||
ASSERT_NO_THROW(addTestOptions(host, formatted, DHCP4_AND_DHCP6));
|
||||
// Insert host, options and IPv6 reservations into respective tables.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// getAll(identifier_type, identifier, identifier_size)
|
||||
ConstHostCollection hosts_by_id =
|
||||
@ -990,7 +1049,9 @@ GenericHostDataSourceTest::testMultipleClientClasses4() {
|
||||
}
|
||||
|
||||
// Add the host.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// Subnet id will be used in queries to the database.
|
||||
SubnetID subnet_id = host->getIPv4SubnetID();
|
||||
@ -1055,7 +1116,9 @@ GenericHostDataSourceTest::testMultipleClientClasses6() {
|
||||
}
|
||||
|
||||
// Add the host.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// Subnet id will be used in queries to the database.
|
||||
SubnetID subnet_id = host->getIPv6SubnetID();
|
||||
@ -1124,7 +1187,9 @@ GenericHostDataSourceTest::testMultipleClientClassesBoth() {
|
||||
}
|
||||
|
||||
// Add the host.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// Subnet id will be used in queries to the database.
|
||||
SubnetID subnet_id = host->getIPv6SubnetID();
|
||||
@ -1153,7 +1218,9 @@ GenericHostDataSourceTest::testMessageFields4() {
|
||||
});
|
||||
|
||||
// Add the host.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// Subnet id will be used in queries to the database.
|
||||
SubnetID subnet_id = host->getIPv4SubnetID();
|
||||
@ -1282,7 +1349,9 @@ void GenericHostDataSourceTest::testDeleteByAddr4() {
|
||||
SubnetID subnet1 = host1->getIPv4SubnetID();
|
||||
|
||||
// ... and add it to the data source.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host1));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host1));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// And then try to retrieve it back.
|
||||
ConstHostPtr before = hdsptr_->get4(subnet1, IOAddress("192.0.2.1"));
|
||||
@ -1309,7 +1378,9 @@ void GenericHostDataSourceTest::testDeleteById4() {
|
||||
SubnetID subnet1 = host1->getIPv4SubnetID();
|
||||
|
||||
// ... and add it to the data source.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host1));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host1));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// And then try to retrieve it back.
|
||||
ConstHostPtr before = hdsptr_->get4(subnet1,
|
||||
@ -1350,7 +1421,9 @@ void GenericHostDataSourceTest::testDeleteById4Options() {
|
||||
SubnetID subnet1 = host1->getIPv4SubnetID();
|
||||
|
||||
// ... and add it to the data source.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host1));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host1));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// There must be some options
|
||||
EXPECT_NE(0, countDBOptions4());
|
||||
@ -1391,7 +1464,9 @@ void GenericHostDataSourceTest::testDeleteById6() {
|
||||
SubnetID subnet1 = host1->getIPv6SubnetID();
|
||||
|
||||
// ... and add it to the data source.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host1));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host1));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// And then try to retrieve it back.
|
||||
ConstHostPtr before = hdsptr_->get6(subnet1,
|
||||
@ -1427,7 +1502,9 @@ void GenericHostDataSourceTest::testDeleteById6Options() {
|
||||
ASSERT_NO_THROW(addTestOptions(host1, true, DHCP6_ONLY));
|
||||
|
||||
// ... and add it to the data source.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host1));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host1));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// Check that the options are stored...
|
||||
EXPECT_NE(0, countDBOptions6());
|
||||
@ -1475,7 +1552,9 @@ GenericHostDataSourceTest::testMultipleHostsNoAddress4() {
|
||||
host1->setIPv4SubnetID(1);
|
||||
host1->setIPv6SubnetID(0);
|
||||
// Add the host to the database.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host1));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host1));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// An attempt to add this host again should fail due to client identifier
|
||||
// duplication.
|
||||
@ -1487,7 +1566,8 @@ GenericHostDataSourceTest::testMultipleHostsNoAddress4() {
|
||||
HostPtr host2 = HostDataSourceUtils::initializeHost4("0.0.0.0", Host::IDENT_HWADDR);
|
||||
host2->setIPv4SubnetID(1);
|
||||
host2->setIPv6SubnetID(0);
|
||||
ASSERT_NO_THROW(hdsptr_->add(host2));
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host2));
|
||||
EXPECT_TRUE(added);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1500,7 +1580,9 @@ GenericHostDataSourceTest::testMultipleHosts6() {
|
||||
host1->setIPv4SubnetID(0);
|
||||
host1->setIPv6SubnetID(1);
|
||||
// Add the host to the database.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host1));
|
||||
bool added = false;
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host1));
|
||||
EXPECT_TRUE(added);
|
||||
|
||||
// An attempt to add this host again should fail due to client identifier
|
||||
// duplication.
|
||||
@ -1510,7 +1592,8 @@ GenericHostDataSourceTest::testMultipleHosts6() {
|
||||
host2->setIPv4SubnetID(0);
|
||||
host2->setIPv6SubnetID(1);
|
||||
// Add the host to the database.
|
||||
ASSERT_NO_THROW(hdsptr_->add(host2));
|
||||
ASSERT_NO_THROW(added = hdsptr_->add(host2));
|
||||
EXPECT_TRUE(added);
|
||||
}
|
||||
|
||||
} // namespace test
|
233
src/lib/dhcpsrv/testutils/memory_host_data_source.cc
Normal file
233
src/lib/dhcpsrv/testutils/memory_host_data_source.cc
Normal file
@ -0,0 +1,233 @@
|
||||
// Copyright (C) 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
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <dhcpsrv/testutils/memory_host_data_source.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
namespace test {
|
||||
|
||||
ConstHostCollection
|
||||
MemHostDataSource::getAll(const HWAddrPtr& /*hwaddr*/,
|
||||
const DuidPtr& /*duid*/) const {
|
||||
return (ConstHostCollection());
|
||||
}
|
||||
|
||||
ConstHostCollection
|
||||
MemHostDataSource::getAll(const Host::IdentifierType& /*identifier_type*/,
|
||||
const uint8_t* /*identifier_begin*/,
|
||||
const size_t /*identifier_len*/) const {
|
||||
return (ConstHostCollection());
|
||||
}
|
||||
|
||||
ConstHostCollection
|
||||
MemHostDataSource::getAll4(const asiolink::IOAddress& /*address*/) const {
|
||||
return (ConstHostCollection());
|
||||
}
|
||||
|
||||
ConstHostPtr
|
||||
MemHostDataSource::get4(const SubnetID& /*subnet_id*/,
|
||||
const HWAddrPtr& /*hwaddr*/,
|
||||
const DuidPtr& /*duid*/) const {
|
||||
return (ConstHostPtr());
|
||||
}
|
||||
|
||||
ConstHostPtr
|
||||
MemHostDataSource::get4(const SubnetID& subnet_id,
|
||||
const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin,
|
||||
const size_t identifier_len) const {
|
||||
vector<uint8_t> ident(identifier_begin, identifier_begin + identifier_len);
|
||||
for (auto h = store_.begin(); h != store_.end(); ++h) {
|
||||
// If either subnet-id or identifier type do not match,
|
||||
// it's not our host
|
||||
if (((*h)->getIPv4SubnetID() != subnet_id) ||
|
||||
((*h)->getIdentifierType() != identifier_type)) {
|
||||
continue;
|
||||
}
|
||||
// If the identifier matches, we found it!
|
||||
if ((*h)->getIdentifier() == ident) {
|
||||
return (*h);
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing found
|
||||
return (ConstHostPtr());
|
||||
}
|
||||
|
||||
ConstHostPtr
|
||||
MemHostDataSource::get6(const SubnetID& subnet_id,
|
||||
const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin,
|
||||
const size_t identifier_len) const {
|
||||
vector<uint8_t> ident(identifier_begin, identifier_begin + identifier_len);
|
||||
for (auto h = store_.begin(); h != store_.end(); ++h) {
|
||||
// If either subnet-id or identifier type do not match,
|
||||
// it's not our host
|
||||
if (((*h)->getIPv6SubnetID() != subnet_id) ||
|
||||
((*h)->getIdentifierType() != identifier_type)) {
|
||||
continue;
|
||||
}
|
||||
// If the identifier matches, we found it!
|
||||
if ((*h)->getIdentifier() == ident) {
|
||||
return (*h);
|
||||
}
|
||||
}
|
||||
|
||||
return (ConstHostPtr());
|
||||
}
|
||||
|
||||
ConstHostPtr
|
||||
MemHostDataSource::get4(const SubnetID& subnet_id,
|
||||
const asiolink::IOAddress& address) const {
|
||||
for (auto h = store_.begin(); h != store_.end(); ++h) {
|
||||
if ((*h)->getIPv4SubnetID() == subnet_id &&
|
||||
(*h)->getIPv4Reservation() == address) {
|
||||
return (*h);
|
||||
}
|
||||
}
|
||||
|
||||
return (ConstHostPtr());
|
||||
}
|
||||
|
||||
ConstHostPtr
|
||||
MemHostDataSource::get6(const SubnetID& /*subnet_id*/,
|
||||
const DuidPtr& /*duid*/,
|
||||
const HWAddrPtr& /*hwaddr*/) const {
|
||||
return (ConstHostPtr());
|
||||
}
|
||||
|
||||
ConstHostPtr
|
||||
MemHostDataSource::get6(const asiolink::IOAddress& /*prefix*/,
|
||||
const uint8_t /*prefix_len*/) const {
|
||||
return (ConstHostPtr());
|
||||
}
|
||||
|
||||
ConstHostPtr
|
||||
MemHostDataSource::get6(const SubnetID& subnet_id,
|
||||
const asiolink::IOAddress& address) const {
|
||||
for (auto h = store_.begin(); h != store_.end(); ++h) {
|
||||
|
||||
// Naive approach: check hosts one by one
|
||||
|
||||
// First check: subnet-id must match.
|
||||
if ((*h)->getIPv6SubnetID() != subnet_id) {
|
||||
// wrong subnet-id? ok, skip this one
|
||||
continue;
|
||||
}
|
||||
|
||||
// Second check: the v6 reservation must much. This is very simple
|
||||
// as we ignore the reservation type.
|
||||
auto resrvs = (*h)->getIPv6Reservations();
|
||||
for (auto r = resrvs.first; r != resrvs.second; ++r) {
|
||||
if ((*r).second.getPrefix() == address) {
|
||||
return (*h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (ConstHostPtr());
|
||||
}
|
||||
|
||||
bool
|
||||
MemHostDataSource::add(const HostPtr& host) {
|
||||
store_.push_back(host);
|
||||
return (true);
|
||||
}
|
||||
|
||||
bool
|
||||
MemHostDataSource::del(const SubnetID& subnet_id,
|
||||
const asiolink::IOAddress& addr) {
|
||||
for (auto h = store_.begin(); h != store_.end(); ++h) {
|
||||
if (addr.isV4()) {
|
||||
if ((*h)->getIPv4SubnetID() == subnet_id &&
|
||||
(*h)->getIPv4Reservation() == addr) {
|
||||
store_.erase(h);
|
||||
return (true);
|
||||
}
|
||||
} else {
|
||||
|
||||
if ((*h)->getIPv6SubnetID() != subnet_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Second check: the v6 reservation must much. This is very simple
|
||||
// as we ignore the reservation type.
|
||||
auto resrvs = (*h)->getIPv6Reservations();
|
||||
for (auto r = resrvs.first; r != resrvs.second; ++r) {
|
||||
if ((*r).second.getPrefix() == addr) {
|
||||
store_.erase(h);
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
bool
|
||||
MemHostDataSource::del4(const SubnetID& subnet_id,
|
||||
const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin,
|
||||
const size_t identifier_len) {
|
||||
vector<uint8_t> ident(identifier_begin, identifier_begin + identifier_len);
|
||||
for (auto h = store_.begin(); h != store_.end(); ++h) {
|
||||
// If either subnet-id or identifier type do not match,
|
||||
// it's not our host
|
||||
if (((*h)->getIPv4SubnetID() != subnet_id) ||
|
||||
((*h)->getIdentifierType() != identifier_type)) {
|
||||
continue;
|
||||
}
|
||||
// If the identifier matches, we found it!
|
||||
if ((*h)->getIdentifier() == ident) {
|
||||
store_.erase(h);
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
bool
|
||||
MemHostDataSource::del6(const SubnetID& subnet_id,
|
||||
const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin,
|
||||
const size_t identifier_len) {
|
||||
vector<uint8_t> ident(identifier_begin, identifier_begin + identifier_len);
|
||||
for (auto h = store_.begin(); h != store_.end(); ++h) {
|
||||
// If either subnet-id or identifier type do not match,
|
||||
// it's not our host
|
||||
if (((*h)->getIPv6SubnetID() != subnet_id) ||
|
||||
((*h)->getIdentifierType() != identifier_type)) {
|
||||
continue;
|
||||
}
|
||||
// If the identifier matches, we found it!
|
||||
if ((*h)->getIdentifier() == ident) {
|
||||
store_.erase(h);
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
size_t
|
||||
MemHostDataSource::size() const {
|
||||
return (store_.size());
|
||||
}
|
||||
|
||||
BaseHostDataSource*
|
||||
memFactory(const DatabaseConnection::ParameterMap& /*parameters*/) {
|
||||
return (new MemHostDataSource());
|
||||
}
|
||||
|
||||
} // namespace isc::dhcp::test
|
||||
} // namespace isc::dhcp
|
||||
} // namespace isc
|
235
src/lib/dhcpsrv/testutils/memory_host_data_source.h
Normal file
235
src/lib/dhcpsrv/testutils/memory_host_data_source.h
Normal file
@ -0,0 +1,235 @@
|
||||
// Copyright (C) 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
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef MEMORY_HOST_DATA_SOURCE_H
|
||||
#define MEMORY_HOST_DATA_SOURCE_H
|
||||
|
||||
#include <dhcpsrv/host_data_source_factory.h>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
namespace test {
|
||||
|
||||
/// @brief Simple host data source implementation for tests.
|
||||
///
|
||||
/// It used vector<HostPtr> as a storage and iterates through all hosts when
|
||||
/// conducting operations. Most operations are skeleton methods that don't
|
||||
/// work, just several are implemented. Those are used in the tests.
|
||||
class MemHostDataSource : public virtual BaseHostDataSource {
|
||||
public:
|
||||
|
||||
/// @brief Destructor.
|
||||
virtual ~MemHostDataSource() { }
|
||||
|
||||
/// BaseHostDataSource methods.
|
||||
|
||||
/// @brief Return all hosts for the specified HW address or DUID.
|
||||
///
|
||||
/// @param hwaddr HW address of the client or NULL if no HW address
|
||||
/// available.
|
||||
/// @param duid client id or NULL if not available, e.g. DHCPv4 client case.
|
||||
/// @return Empty collection of const @c Host objects.
|
||||
virtual ConstHostCollection
|
||||
getAll(const HWAddrPtr& hwaddr, const DuidPtr& duid = DuidPtr()) const;
|
||||
|
||||
/// @brief Return all hosts connected to any subnet for which reservations
|
||||
/// have been made using a specified identifier.
|
||||
///
|
||||
/// @param identifier_type Identifier type.
|
||||
/// @param identifier_begin Pointer to a beginning of a buffer containing
|
||||
/// an identifier.
|
||||
/// @param identifier_len Identifier length.
|
||||
/// @return Empty collection of const @c Host objects.
|
||||
virtual ConstHostCollection
|
||||
getAll(const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin,
|
||||
const size_t identifier_len) const;
|
||||
|
||||
/// @brief Returns a collection of hosts using the specified IPv4 address.
|
||||
///
|
||||
/// @param address IPv4 address for which the @c Host object is searched.
|
||||
/// @return Empty collection of const @c Host objects.
|
||||
virtual ConstHostCollection
|
||||
getAll4(const asiolink::IOAddress& address) const;
|
||||
|
||||
/// @brief Returns a host connected to the IPv4 subnet.
|
||||
///
|
||||
/// @param subnet_id Subnet identifier.
|
||||
/// @param hwaddr HW address of the client or NULL if no HW address
|
||||
/// available.
|
||||
/// @param duid client id or NULL if not available.
|
||||
/// @return Const @c Host object using a specified HW address or DUID.
|
||||
virtual ConstHostPtr
|
||||
get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr,
|
||||
const DuidPtr& duid = DuidPtr()) const;
|
||||
|
||||
|
||||
/// @brief Returns a host connected to the IPv4 subnet.
|
||||
///
|
||||
/// @param subnet_id Subnet identifier.
|
||||
/// @param identifier_type Identifier type.
|
||||
/// @param identifier_begin Pointer to a beginning of a buffer containing
|
||||
/// an identifier.
|
||||
/// @param identifier_len Identifier length.
|
||||
/// @return Const @c Host object for which reservation has been made using
|
||||
/// the specified identifier.
|
||||
virtual ConstHostPtr
|
||||
get4(const SubnetID& subnet_id,
|
||||
const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin,
|
||||
const size_t identifier_len) const;
|
||||
|
||||
/// @brief Returns a host connected to the IPv4 subnet and having
|
||||
/// a reservation for a specified IPv4 address.
|
||||
///
|
||||
/// @param subnet_id Subnet identifier.
|
||||
/// @param address reserved IPv4 address.
|
||||
/// @return Const @c Host object using a specified IPv4 address.
|
||||
virtual ConstHostPtr
|
||||
get4(const SubnetID& subnet_id,
|
||||
const asiolink::IOAddress& address) const;
|
||||
|
||||
/// @brief Returns a host connected to the IPv6 subnet.
|
||||
///
|
||||
/// @param subnet_id Subnet identifier.
|
||||
/// @param hwaddr HW address of the client or NULL if no HW address
|
||||
/// available.
|
||||
/// @param duid DUID or NULL if not available.
|
||||
/// @return Const @c Host object using a specified HW address or DUID.
|
||||
virtual ConstHostPtr
|
||||
get6(const SubnetID& subnet_id, const DuidPtr& duid,
|
||||
const HWAddrPtr& hwaddr = HWAddrPtr()) const;
|
||||
|
||||
/// @brief Returns a host connected to the IPv6 subnet.
|
||||
///
|
||||
/// @param subnet_id Subnet identifier.
|
||||
/// @param identifier_type Identifier type.
|
||||
/// @param identifier_begin Pointer to a beginning of a buffer containing
|
||||
/// an identifier.
|
||||
/// @param identifier_len Identifier length.
|
||||
/// @return Const @c Host object for which reservation has been made using
|
||||
/// the specified identifier.
|
||||
virtual ConstHostPtr
|
||||
get6(const SubnetID& subnet_id,
|
||||
const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin,
|
||||
const size_t identifier_len) const;
|
||||
|
||||
/// @brief Returns a host using the specified IPv6 prefix.
|
||||
///
|
||||
/// @param prefix IPv6 prefix for which the @c Host object is searched.
|
||||
/// @param prefix_len IPv6 prefix length.
|
||||
/// @return Const @c Host object using a specified HW address or DUID.
|
||||
virtual ConstHostPtr
|
||||
get6(const asiolink::IOAddress& prefix, const uint8_t prefix_len) const;
|
||||
|
||||
/// @brief Returns a host connected to the IPv6 subnet and having
|
||||
/// a reservation for a specified IPv6 address or prefix.
|
||||
///
|
||||
/// @param subnet_id Subnet identifier.
|
||||
/// @param address reserved IPv6 address/prefix.
|
||||
/// @return Const @c Host object using a specified IPv6 address/prefix.
|
||||
virtual ConstHostPtr
|
||||
get6(const SubnetID& subnet_id, const asiolink::IOAddress& address) const;
|
||||
|
||||
/// @brief Adds a new host to the collection.
|
||||
///
|
||||
/// @param host Pointer to the new @c Host object being added.
|
||||
/// @return true if addition was successful.
|
||||
virtual bool add(const HostPtr& host);
|
||||
|
||||
/// @brief Attempts to delete a host by (subnet-id, address)
|
||||
///
|
||||
/// @param subnet_id subnet identifier.
|
||||
/// @param addr specified address.
|
||||
/// @return true if deletion was successful, false if the host was not there.
|
||||
/// @throw various exceptions in case of errors
|
||||
virtual bool del(const SubnetID& subnet_id, const asiolink::IOAddress& addr);
|
||||
|
||||
/// @brief Attempts to delete a host by (subnet-id4, identifier, identifier-type)
|
||||
///
|
||||
/// @param subnet_id IPv4 Subnet identifier.
|
||||
/// @param identifier_type Identifier type.
|
||||
/// @param identifier_begin Pointer to a beginning of a buffer containing
|
||||
/// an identifier.
|
||||
/// @param identifier_len Identifier length.
|
||||
/// @return true if deletion was successful, false if the host was not there.
|
||||
/// @throw various exceptions in case of errors
|
||||
virtual bool del4(const SubnetID& subnet_id,
|
||||
const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin, const size_t identifier_len);
|
||||
|
||||
/// @brief Attempts to delete a host by (subnet-id6, identifier, identifier-type)
|
||||
///
|
||||
/// @param subnet_id IPv6 Subnet identifier.
|
||||
/// @param identifier_type Identifier type.
|
||||
/// @param identifier_begin Pointer to a beginning of a buffer containing
|
||||
/// an identifier.
|
||||
/// @param identifier_len Identifier length.
|
||||
/// @return true if deletion was successful, false if the host was not there.
|
||||
/// @throw various exceptions in case of errors
|
||||
virtual bool del6(const SubnetID& subnet_id,
|
||||
const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin, const size_t identifier_len);
|
||||
|
||||
/// @brief Return backend type
|
||||
///
|
||||
/// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
|
||||
///
|
||||
/// @return Type of the backend.
|
||||
virtual std::string getType() const {
|
||||
return ("mem");
|
||||
}
|
||||
|
||||
/// More lease backend?
|
||||
|
||||
/// @brief Returns name of the database or file used by the backend
|
||||
/// @return "mem" string"
|
||||
virtual std::string getName() const {
|
||||
return (std::string("mem"));
|
||||
}
|
||||
|
||||
/// @brief Returns description of the backend.
|
||||
/// @return description
|
||||
virtual std::string getDescription() const {
|
||||
return (std::string("In memory storage, mostly useful for testing."));
|
||||
}
|
||||
|
||||
/// @brief Returns version this backend
|
||||
/// @return two numbers that each represent practical value of this backend.
|
||||
virtual std::pair<uint32_t, uint32_t> getVersion() const {
|
||||
return (std::make_pair(0,0));
|
||||
}
|
||||
|
||||
/// @brief Returns store size.
|
||||
/// @return number of hosts in the store.
|
||||
virtual size_t size() const;
|
||||
|
||||
protected:
|
||||
// This is very simple storage.
|
||||
|
||||
/// @brief Store
|
||||
std::vector<HostPtr> store_;
|
||||
};
|
||||
|
||||
/// Pointer to the Mem host data source.
|
||||
typedef boost::shared_ptr<MemHostDataSource> MemHostDataSourcePtr;
|
||||
|
||||
/// @brief Factory function.
|
||||
///
|
||||
/// @param parameters
|
||||
/// @return A pointer to a base host data source instance.
|
||||
BaseHostDataSource*
|
||||
memFactory(const DatabaseConnection::ParameterMap& /*parameters*/);
|
||||
|
||||
} // namespace isc::dhcp::test
|
||||
} // namespace isc::dhcp
|
||||
} // namespace isc
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user