From 8d05ba02b222fce24a000b7941f4bb7a5010d783 Mon Sep 17 00:00:00 2001 From: Razvan Becheriu Date: Wed, 11 Nov 2020 11:06:18 +0200 Subject: [PATCH] [#1405] merged first pass --- doc/examples/kea4/all-keys.json | 23 +- doc/examples/kea6/all-keys.json | 23 +- doc/sphinx/arm/dhcp4-srv.rst | 48 +++- doc/sphinx/arm/dhcp6-srv.rst | 58 ++-- doc/sphinx/arm/hooks.rst | 7 +- src/bin/admin/tests/mysql_tests.sh.in | 16 +- src/bin/dhcp4/tests/dora_unittest.cc | 16 +- src/bin/dhcp4/tests/host_unittest.cc | 61 ++-- src/bin/dhcp6/dhcp6_srv.cc | 1 - src/bin/dhcp6/tests/host_unittest.cc | 27 +- src/bin/keactrl/kea-dhcp4.conf.pre | 6 +- src/lib/dhcpsrv/Makefile.am | 5 - src/lib/dhcpsrv/alloc_engine.h | 29 +- src/lib/dhcpsrv/network.cc | 73 ++--- src/lib/dhcpsrv/network.h | 197 ++++--------- .../parsers/reservation_modes_parser.cc | 68 ----- .../parsers/reservation_modes_parser.h | 42 --- src/lib/dhcpsrv/parsers/simple_parser4.cc | 16 +- src/lib/dhcpsrv/parsers/simple_parser6.cc | 16 +- src/lib/dhcpsrv/tests/Makefile.am | 1 - .../dhcpsrv/tests/alloc_engine4_unittest.cc | 26 +- .../dhcpsrv/tests/alloc_engine6_unittest.cc | 20 +- .../dhcpsrv/tests/cfg_subnets4_unittest.cc | 22 +- .../dhcpsrv/tests/cfg_subnets6_unittest.cc | 22 +- .../dhcpsrv/tests/dhcp_parsers_unittest.cc | 40 ++- src/lib/dhcpsrv/tests/network_unittest.cc | 42 ++- .../reservation_modes_parser_unittest.cc | 272 ------------------ .../tests/shared_network_parser_unittest.cc | 16 +- .../dhcpsrv/tests/shared_network_unittest.cc | 33 ++- src/lib/dhcpsrv/tests/subnet_unittest.cc | 20 +- .../scripts/mysql/dhcpdb_create.mysql | 43 +-- .../scripts/mysql/upgrade_9.4_to_9.5.sh.in | 140 +++++++-- 32 files changed, 611 insertions(+), 818 deletions(-) delete mode 100644 src/lib/dhcpsrv/parsers/reservation_modes_parser.cc delete mode 100644 src/lib/dhcpsrv/parsers/reservation_modes_parser.h delete mode 100644 src/lib/dhcpsrv/tests/reservation_modes_parser_unittest.cc diff --git a/doc/examples/kea4/all-keys.json b/doc/examples/kea4/all-keys.json index 99d3d6ab8c..19d0b1ac7d 100644 --- a/doc/examples/kea4/all-keys.json +++ b/doc/examples/kea4/all-keys.json @@ -695,8 +695,9 @@ // Enumeration specifying server's mode of operation when it // fetches host reservations. - // It is deprecated by the "reservations-out-of-pool", - // "reservations-in-subnet" and "reservations-global" parameters. + // It is replaced by the "reservations-global", + // "reservations-in-subnet" and "reservations-out-of-pool" + // parameters. // "reservation-mode": "all", // Specify if server should lookup global reservations. @@ -705,7 +706,8 @@ // Specify if server should lookup in-subnet reservations. "reservations-in-subnet": true, - // Specify if server should lookup out-of-pool reservations. + // Specify if server can assume that all reserved addresses + // are out-of-pool. "reservations-out-of-pool": false, // List of client classes which must be evaluated when this shared @@ -869,8 +871,9 @@ // Enumeration specifying server's mode of operation when it // fetches host reservations. - // It is deprecated by the "reservations-out-of-pool", - // "reservations-in-subnet" and "reservations-global" parameters. + // It is replaced by the "reservations-global", + // "reservations-in-subnet" and + // "reservations-out-of-pool" parameters. // "reservation-mode": "all", // Specify if server should lookup global reservations. @@ -879,7 +882,8 @@ // Specify if server should lookup in-subnet reservations. "reservations-in-subnet": true, - // Specify if server should lookup out-of-pool reservations. + // Specify if server can assume that all reserved + // addresses are out-of-pool. "reservations-out-of-pool": false, // Subnet level compute T1 and T2 timers. @@ -1008,8 +1012,8 @@ }, // Fetches host reservations. - // It is deprecated by the "reservations-out-of-pool", - // "reservations-in-subnet" and "reservations-global" parameters. + // It is replaced by the "reservations-global", + // "reservations-in-subnet" and "reservations-out-of-pool" parameters. // "reservation-mode": "all", // Specify if server should lookup global reservations. @@ -1018,7 +1022,8 @@ // Specify if server should lookup in-subnet reservations. "reservations-in-subnet": true, - // Specify if server should lookup out-of-pool reservations. + // Specify if server can assume that all reserved addresses + // are out-of-pool. "reservations-out-of-pool": false, // Global compute T1 and T2 timers. diff --git a/doc/examples/kea6/all-keys.json b/doc/examples/kea6/all-keys.json index 8f191a4bdc..da08911928 100644 --- a/doc/examples/kea6/all-keys.json +++ b/doc/examples/kea6/all-keys.json @@ -653,8 +653,9 @@ // Enumeration specifying server's mode of operation when it // fetches host reservations. - // It is deprecated by the "reservations-out-of-pool", - // "reservations-in-subnet" and "reservations-global" parameters. + // It is replaced by the "reservations-global", + // "reservations-in-subnet" and "reservations-out-of-pool" + // parameters. // "reservation-mode": "all", // Specify if server should lookup global reservations. @@ -663,7 +664,8 @@ // Specify if server should lookup in-subnet reservations. "reservations-in-subnet": true, - // Specify if server should lookup out-of-pool reservations. + // Specify if server can assume that all reserved addresses + // are out-of-pool. "reservations-out-of-pool": false, // List of client classes which must be evaluated when this shared @@ -850,8 +852,9 @@ // Enumeration specifying server's mode of operation when it // fetches host reservations. - // It is deprecated by the "reservations-out-of-pool", - // "reservations-in-subnet" and "reservations-global" parameters. + // It is replaced by the "reservations-global", + // "reservations-in-subnet" and + // "reservations-out-of-pool" parameters. // "reservation-mode": "all", // Specify if server should lookup global reservations. @@ -860,7 +863,8 @@ // Specify if server should lookup in-subnet reservations. "reservations-in-subnet": true, - // Specify if server should lookup out-of-pool reservations. + // Specify if server can assume that all reserved + // addresses are out-of-pool. "reservations-out-of-pool": false, // Subnet level compute T1 and T2 timers. @@ -986,8 +990,8 @@ }, // Fetches host reservations. - // It is deprecated by the "reservations-out-of-pool", - // "reservations-in-subnet" and "reservations-global" parameters. + // It is replaced by the "reservations-global", + // "reservations-in-subnet" and "reservations-out-of-pool" parameters. // "reservation-mode": "all", // Specify if server should lookup global reservations. @@ -996,7 +1000,8 @@ // Specify if server should lookup in-subnet reservations. "reservations-in-subnet": true, - // Specify if server should lookup out-of-pool reservations. + // Specify if server can assume that all reserved addresses + // are out-of-pool. "reservations-out-of-pool": false, // Data directory. diff --git a/doc/sphinx/arm/dhcp4-srv.rst b/doc/sphinx/arm/dhcp4-srv.rst index b5991a3390..1fcd8c0fa5 100644 --- a/doc/sphinx/arm/dhcp4-srv.rst +++ b/doc/sphinx/arm/dhcp4-srv.rst @@ -4106,6 +4106,15 @@ another. that must be given due consideration when using them, please see :ref:`reservation4-conflict` for more details. +.. note:: + + Beginning with Kea 1.9.1 reservation mode was replaced by three + boolean flags ``"reservations-global"``, ``"reservations-in-subnet"`` + and ``"reservations-out-of-pool"`` which allow to configure host + reservations both global and in a subnet. In such case a subnet + host reservation has the preference on a global reservation + when both exist for the same client. + .. _reservation4-conflict: Conflicts in DHCPv4 Reservations @@ -4622,11 +4631,26 @@ An example configuration using global reservations is shown below: ] } -Since Kea 1.9.1, the ``reservation-mode`` is deprecated by the -``reservations-out-of-pool``, ``reservations-in-subnet`` and -``reservations-global`` flags. +Since Kea 1.9.1, the ``reservation-mode`` is replaced by the +``reservations-global``, ``reservations-in-subnet`` and +``reservations-out-of-pool`` flags. The flags can be activated independently and can produce various combinations, -some of them being unsupported by the deprecated ``reservation-mode``. +some of them being unsuported by the deprecated ``reservation-mode``. + +The meaning of these flags are: + +- ``reservations-global``: fetch global reservations. + +- ``reservations-in-subnet``: fetch subnet reservations. For a shared network + this includes all subnets member of the shared network. + +- ``reservations-out-of-pool``: the makes sense only when the + ``reservations-in-subnet`` flag is true. When ``reservations-out-of-pool`` + is true the server may assume that all host reservations of the subnet are + for addresses that do not belong to the dynamic pool as described in the + ``out-of-pool`` reservation mode. + +The ``reservation-mode`` will be deprecated in a future Kea version. The correspondence of old values are: @@ -4881,14 +4905,16 @@ following can be used: "valid-lifetime": 600, "subnet4": [ { "subnet": "10.0.0.0/24", - # It is deprecated by the "reservations-out-of-pool", - # "reservations-in-subnet" and "reservations-global" parameters. + # It is replaced by the "reservations-global" + # "reservations-in-subnet" and "reservations-out-of-pool" + # parameters. # "reservation-mode": "global", # Specify if server should lookup global reservations. "reservations-global": true, # Specify if server should lookup in-subnet reservations. "reservations-in-subnet": false, - # Specify if server should lookup out-of-pool reservations. + # Specify if server can assume that all reserved addresses + # are out-of-pool. "reservations-out-of-pool": false, "pools": [ { "pool": "10.0.0.10-10.0.0.100" } ] } ] @@ -4992,14 +5018,14 @@ following example: "hw-address": "aa:bb:cc:dd:ee:fe", "client-classes": [ "reserved_class" ] }], - # It is deprecated by the "reservations-out-of-pool", - # "reservations-in-subnet" and "reservations-global" parameters. - # "reservation-mode": "global", + # It is replaced by the "reservations-global" + # "reservations-in-subnet" and "reservations-out-of-pool" parameters. # Specify if server should lookup global reservations. "reservations-global": true, # Specify if server should lookup in-subnet reservations. "reservations-in-subnet": false, - # Specify if server should lookup out-of-pool reservations. + # Specify if server can assume that all reserved addresses + # are out-of-pool. "reservations-out-of-pool": false, "shared-networks": [{ "subnet4": [ diff --git a/doc/sphinx/arm/dhcp6-srv.rst b/doc/sphinx/arm/dhcp6-srv.rst index 8fecffdadc..285478912f 100644 --- a/doc/sphinx/arm/dhcp6-srv.rst +++ b/doc/sphinx/arm/dhcp6-srv.rst @@ -3606,6 +3606,15 @@ another. that must be given due consideration. Please see :ref:`reservation6-conflict` for more details. +.. note:: + + Beginning with Kea 1.9.1 reservation mode was replaced by three + boolean flags ``"reservations-global"``, ``"reservations-in-subnet"`` + and ``"reservations-out-of-pool"`` which allow to configure host + reservations both global and in a subnet. In such case a subnet + host reservation has the preference on a global reservation + when both exist for the same client. + .. _reservation6-conflict: Conflicts in DHCPv6 Reservations @@ -4031,11 +4040,11 @@ An example configuration that disables reservations looks as follows: "Dhcp6": { "subnet6": [ - { + { "subnet": "2001:db8:1::/64", "reservation-mode": "disabled", ... - } + } ] } @@ -4067,11 +4076,26 @@ An example configuration using global reservations is shown below: ] } -Since Kea 1.9.1, the ``reservation-mode`` is deprecated by the -``reservations-out-of-pool``, ``reservations-in-subnet`` and -``reservations-global`` flags. +Since Kea 1.9.1, the ``reservation-mode`` is replaced by the +``reservations-global``, ``reservations-in-subnet`` and +``reservations-out-of-pool`` flags. The flags can be activated independently and can produce various combinations, -some of them being unsupported by the deprecated ``reservation-mode``. +some of them being unsuported by the deprecated ``reservation-mode``. + +The meaning of these flags are: + +- ``reservations-global``: fetch global reservations. + +- ``reservations-in-subnet``: fetch subnet reservations. For a shared network + this includes all subnets member of the shared network. + +- ``reservations-out-of-pool``: the makes sense only when the + ``reservations-in-subnet`` flag is true. When ``reservations-out-of-pool`` + is true the server may assume that all host reservations of the subnet are + for addresses or prefixes that do not belong to the dynamic pool as described + in the ``out-of-pool`` reservation mode. + +The ``reservation-mode`` will be deprecated in a future Kea version. The correspondence of old values are: @@ -4166,7 +4190,7 @@ For this reason, the ``in-subnet`` can be omitted when ``out-of-pool`` is set. :: - "Dhcp4": { + "Dhcp6": { "reservations-global": true, "reservations-out-of-pool": true, @@ -4182,13 +4206,13 @@ An example configuration that disables reservations looks as follows: "Dhcp6": { "subnet6": [ - { + { "subnet": "2001:db8:1::/64", "reservations-global": false, "reservations-in-subnet": false, "reservations-out-of-pool": false, ... - } + } ] } @@ -4322,14 +4346,16 @@ following can be used: "valid-lifetime": 600, "subnet4": [ { "subnet": "2001:db8:1::/64", - # It is deprecated by the "reservations-out-of-pool", - # "reservations-in-subnet" and "reservations-global" parameters. + # It is replaced by the "reservations-global" + # "reservations-in-subnet" and "reservations-out-of-pool" + # parameters. # "reservation-mode": "global", # Specify if server should lookup global reservations. "reservations-global": true, # Specify if server should lookup in-subnet reservations. "reservations-in-subnet": false, - # Specify if server should lookup out-of-pool reservations. + # Specify if server can assume that all reserved addresses + # are out-of-pool. "reservations-out-of-pool": false, "pools": [ { "pool": "2001:db8:1::-2001:db8:1::100" } ] } ] @@ -4433,14 +4459,14 @@ following example: "hw-address": "aa:bb:cc:dd:ee:fe", "client-classes": [ "reserved_class" ] }], - # It is deprecated by the "reservations-out-of-pool", - # "reservations-in-subnet" and "reservations-global" parameters. - # "reservation-mode": "global", + # It is replaced by the "reservations-global" + # "reservations-in-subnet" and "reservations-out-of-pool" parameters. # Specify if server should lookup global reservations. "reservations-global": true, # Specify if server should lookup in-subnet reservations. "reservations-in-subnet": false, - # Specify if server should lookup out-of-pool reservations. + # Specify if server can assume that all reserved addresses + # are out-of-pool. "reservations-out-of-pool": false, "shared-networks": [{ "subnet6": [ diff --git a/doc/sphinx/arm/hooks.rst b/doc/sphinx/arm/hooks.rst index 95fceffe81..358d6c5683 100644 --- a/doc/sphinx/arm/hooks.rst +++ b/doc/sphinx/arm/hooks.rst @@ -2655,14 +2655,15 @@ An example response could look as follows: "ip-address": "0.0.0.0" }, "renew-timer": 60, - # It is deprecated by the "reservations-out-of-pool", - # "reservations-in-subnet" and "reservations-global" parameters. + # It is replaced by the "reservations-global" + # "reservations-in-subnet" and "reservations-out-of-pool" parameters. # "reservation-mode": "all", # Specify if server should lookup global reservations. "reservations-global": false, # Specify if server should lookup in-subnet reservations. "reservations-in-subnet": true, - # Specify if server should lookup out-of-pool reservations. + # Specify if server can assume that all reserved addresses + # are out-of-pool. "reservations-out-of-pool": false, "subnet4": [ { diff --git a/src/bin/admin/tests/mysql_tests.sh.in b/src/bin/admin/tests/mysql_tests.sh.in index 55a85ff7ad..ba3a3b5227 100644 --- a/src/bin/admin/tests/mysql_tests.sh.in +++ b/src/bin/admin/tests/mysql_tests.sh.in @@ -513,7 +513,7 @@ EOF run_statement "dhcp4_option_def_server" "$qry" # table: dhcp4_shared_network - qry="select id, name, client_class, interface, match_client_id, modification_ts, rebind_timer, relay, renew_timer, require_client_classes, reservation_mode, user_context, valid_lifetime, authoritative, calculate_tee_times, t1_percent, t2_percent, boot_file_name, next_server, server_hostname from dhcp4_shared_network" + qry="select id, name, client_class, interface, match_client_id, modification_ts, rebind_timer, relay, renew_timer, require_client_classes, user_context, valid_lifetime, authoritative, calculate_tee_times, t1_percent, t2_percent, boot_file_name, next_server, server_hostname from dhcp4_shared_network" run_statement "dhcp4_shared_network" "$qry" # table: dhcp4_shared_network_server @@ -521,7 +521,7 @@ EOF run_statement "dhcp4_shared_network_server" "$qry" # table: dhcp4_subnet - qry="select subnet_prefix, 4o6_interface, 4o6_interface_id, 4o6_subnet, boot_file_name, client_class, interface, match_client_id, modification_ts, next_server, rebind_timer, relay, renew_timer, require_client_classes, reservation_mode, server_hostname, shared_network_name, subnet_id, user_context, valid_lifetime, authoritative, calculate_tee_times, t1_percent, t2_percent from dhcp4_subnet" + qry="select subnet_prefix, 4o6_interface, 4o6_interface_id, 4o6_subnet, boot_file_name, client_class, interface, match_client_id, modification_ts, next_server, rebind_timer, relay, renew_timer, require_client_classes, server_hostname, shared_network_name, subnet_id, user_context, valid_lifetime, authoritative, calculate_tee_times, t1_percent, t2_percent from dhcp4_subnet" run_statement "dhcp4_subnet" "$qry" # table: dhcp4_pool @@ -569,7 +569,7 @@ EOF run_statement "dhcp6_option_def_server" "$qry" # table: dhcp6_shared_network - qry="select id, name, client_class, interface, modification_ts, preferred_lifetime, rapid_commit, rebind_timer, relay, renew_timer, require_client_classes, reservation_mode, user_context, valid_lifetime, calculate_tee_times, t1_percent, t2_percent, interface_id from dhcp6_shared_network" + qry="select id, name, client_class, interface, modification_ts, preferred_lifetime, rapid_commit, rebind_timer, relay, renew_timer, require_client_classes, user_context, valid_lifetime, calculate_tee_times, t1_percent, t2_percent, interface_id from dhcp6_shared_network" run_statement "dhcp6_shared_network" "$qry" # table: dhcp6_shared_network_server @@ -577,7 +577,7 @@ EOF run_statement "dhcp6_shared_network" "$qry" # table: dhcp6_subnet - qry="select subnet_prefix, client_class, interface, modification_ts, preferred_lifetime, rapid_commit, rebind_timer, relay, renew_timer, require_client_classes, reservation_mode, shared_network_name, subnet_id, user_context, valid_lifetime, calculate_tee_times, t1_percent, t2_percent, interface_id from dhcp6_subnet" + qry="select subnet_prefix, client_class, interface, modification_ts, preferred_lifetime, rapid_commit, rebind_timer, relay, renew_timer, require_client_classes, shared_network_name, subnet_id, user_context, valid_lifetime, calculate_tee_times, t1_percent, t2_percent, interface_id from dhcp6_subnet" run_statement "dhcp6_subnet" "$qry" # table: dhcp6_subnet_server @@ -700,19 +700,19 @@ EOF # New lifetime bounds. # table: dhcp4_shared_network - qry="select id, name, client_class, interface, match_client_id, modification_ts, rebind_timer, relay, renew_timer, require_client_classes, reservation_mode, user_context, valid_lifetime, min_valid_lifetime, max_valid_lifetime, authoritative, calculate_tee_times, t1_percent, t2_percent, boot_file_name, next_server, server_hostname from dhcp4_shared_network" + qry="select id, name, client_class, interface, match_client_id, modification_ts, rebind_timer, relay, renew_timer, require_client_classes, user_context, valid_lifetime, min_valid_lifetime, max_valid_lifetime, authoritative, calculate_tee_times, t1_percent, t2_percent, boot_file_name, next_server, server_hostname from dhcp4_shared_network" run_statement "dhcp4_shared_network" "$qry" # table: dhcp4_subnet - qry="select subnet_prefix, 4o6_interface, 4o6_interface_id, 4o6_subnet, boot_file_name, client_class, interface, match_client_id, modification_ts, next_server, rebind_timer, relay, renew_timer, require_client_classes, reservation_mode, server_hostname, shared_network_name, subnet_id, user_context, valid_lifetime, min_valid_lifetime, max_valid_lifetime, authoritative, calculate_tee_times, t1_percent, t2_percent from dhcp4_subnet" + qry="select subnet_prefix, 4o6_interface, 4o6_interface_id, 4o6_subnet, boot_file_name, client_class, interface, match_client_id, modification_ts, next_server, rebind_timer, relay, renew_timer, require_client_classes, server_hostname, shared_network_name, subnet_id, user_context, valid_lifetime, min_valid_lifetime, max_valid_lifetime, authoritative, calculate_tee_times, t1_percent, t2_percent from dhcp4_subnet" run_statement "dhcp4_subnet" "$qry" # table: dhcp6_shared_network - qry="select id, name, client_class, interface, modification_ts, preferred_lifetime, min_preferred_lifetime, max_preferred_lifetime,rapid_commit, rebind_timer, relay, renew_timer, require_client_classes, reservation_mode, user_context, valid_lifetime, min_valid_lifetime, max_valid_lifetime, calculate_tee_times, t1_percent, t2_percent from dhcp6_shared_network" + qry="select id, name, client_class, interface, modification_ts, preferred_lifetime, min_preferred_lifetime, max_preferred_lifetime,rapid_commit, rebind_timer, relay, renew_timer, require_client_classes, user_context, valid_lifetime, min_valid_lifetime, max_valid_lifetime, calculate_tee_times, t1_percent, t2_percent from dhcp6_shared_network" run_statement "dhcp6_shared_network" "$qry" # table: dhcp6_subnet - qry="select subnet_prefix, client_class, interface, modification_ts, preferred_lifetime, min_preferred_lifetime, max_preferred_lifetime, rapid_commit, rebind_timer, relay, renew_timer, require_client_classes, reservation_mode, shared_network_name, subnet_id, user_context, valid_lifetime, min_valid_lifetime, max_valid_lifetime, calculate_tee_times, t1_percent, t2_percent from dhcp6_subnet" + qry="select subnet_prefix, client_class, interface, modification_ts, preferred_lifetime, min_preferred_lifetime, max_preferred_lifetime, rapid_commit, rebind_timer, relay, renew_timer, require_client_classes, shared_network_name, subnet_id, user_context, valid_lifetime, min_valid_lifetime, max_valid_lifetime, calculate_tee_times, t1_percent, t2_percent from dhcp6_subnet" run_statement "dhcp6_subnet" "$qry" # table: dhcp4_pool (should include three new columns) diff --git a/src/bin/dhcp4/tests/dora_unittest.cc b/src/bin/dhcp4/tests/dora_unittest.cc index 7c35d3d7d1..3886e36e00 100644 --- a/src/bin/dhcp4/tests/dora_unittest.cc +++ b/src/bin/dhcp4/tests/dora_unittest.cc @@ -459,7 +459,9 @@ const char* DORA_CONFIGS[] = { "\"subnet4\": [ { " " \"subnet\": \"10.0.0.0/24\"," " \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ]," - " \"reservation-mode\": \"all\"," + " \"reservations-global\": false," + " \"reservations-in-subnet\": true," + " \"reservations-out-of-pool\": false," " \"reservations\": [ " " {" " \"hw-address\": \"aa:bb:cc:dd:ee:ff\"," @@ -477,7 +479,9 @@ const char* DORA_CONFIGS[] = { "\"subnet4\": [ { " " \"subnet\": \"10.0.0.0/24\"," " \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ]," - " \"reservation-mode\": \"disabled\"," + " \"reservations-global\": false," + " \"reservations-in-subnet\": false," + " \"reservations-out-of-pool\": false," " \"reservations\": [ " " {" " \"hw-address\": \"aa:bb:cc:dd:ee:ff\"," @@ -495,7 +499,9 @@ const char* DORA_CONFIGS[] = { "\"subnet4\": [ { " " \"subnet\": \"10.0.0.0/24\"," " \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ]," - " \"reservation-mode\": \"out-of-pool\"," + " \"reservations-global\": false," + " \"reservations-in-subnet\": true," + " \"reservations-out-of-pool\": true," " \"reservations\": [ " " {" " \"hw-address\": \"aa:bb:cc:dd:ee:ff\"," @@ -1803,8 +1809,8 @@ TEST_F(DORATest, reservationModeDisabled) { // Set explicit HW address so as it matches the reservation in the // configuration used below. client.setHWAddress("aa:bb:cc:dd:ee:ff"); - // Configure DHCP server. In this configuration the reservation mode is - // set to disabled. Thus, the server should ignore the reservation for + // Configure DHCP server. In this configuration the reservation flags are + // set to false. Thus, the server should ignore the reservation for // this client. configure(DORA_CONFIGS[13], *client.getServer()); // Client requests the 10.0.0.50 address and the server should assign it diff --git a/src/bin/dhcp4/tests/host_unittest.cc b/src/bin/dhcp4/tests/host_unittest.cc index 10629faea8..55d8c6e579 100644 --- a/src/bin/dhcp4/tests/host_unittest.cc +++ b/src/bin/dhcp4/tests/host_unittest.cc @@ -34,7 +34,7 @@ namespace { /// - 1 subnet: 10.0.0.0/24 const char* CONFIGS[] = { // Configuration 0 - // 1 subnet, mode HR_GLOBAL, + // 1 subnet, global only, // global reservations for different identifier types "{ \"interfaces-config\": {\n" " \"interfaces\": [ \"*\" ]\n" @@ -66,14 +66,17 @@ const char* CONFIGS[] = { "],\n" "\"valid-lifetime\": 600,\n" "\"subnet4\": [ { \n" - " \"subnet\": \"10.0.0.0/24\", \n" + " \"subnet\": \"10.0.0.0/24\",\n" " \"reservations-global\": true,\n" + " \"reservations-in-subnet\": false,\n" + " \"reservations-out-of-pool\": false,\n" " \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ]\n" "} ]\n" "}\n" , - // Configuration 1 global vs in-pool - // 2 subnets, one mode default (aka HR_ALL), one mode HR_GLOBAL + // Configuration 1 global vs in-subnet + // 2 subnets, one default reservations flags (aka in-subnet), + // one reservations flags global only // Host reservations for the same client, one global, one in each subnet "{ \"interfaces-config\": {\n" " \"interfaces\": [ \"*\" ]\n" @@ -103,6 +106,8 @@ const char* CONFIGS[] = { " \"pools\": [ { \"pool\": \"192.0.2.10-192.0.2.63\" } ],\n" " \"interface\": \"eth1\",\n" " \"reservations-global\": true,\n" + " \"reservations-in-subnet\": false,\n" + " \"reservations-out-of-pool\": false,\n" " \"reservations\": [ \n" " {\n" " \"hw-address\": \"aa:bb:cc:dd:ee:ff\",\n" @@ -112,7 +117,7 @@ const char* CONFIGS[] = { "]\n" "}\n" , - // Configuration 2 global and out-of-pool + // Configuration 2 global and in-subnet with out-of-pool "{ \"interfaces-config\": {\n" " \"interfaces\": [ \"*\" ]\n" "},\n" @@ -129,6 +134,8 @@ const char* CONFIGS[] = { " \"id\": 10," " \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ],\n" " \"interface\": \"eth0\",\n" + " \"reservations-global\": false,\n" + " \"reservations-in-subnet\": true,\n" " \"reservations-out-of-pool\": true,\n" " \"reservations\": [ \n" " {\n" @@ -140,7 +147,7 @@ const char* CONFIGS[] = { "]\n" "}\n" , - // Configuration 3 global and all + // Configuration 3 global and in-subnet "{ \"interfaces-config\": {\n" " \"interfaces\": [ \"*\" ]\n" "},\n" @@ -157,7 +164,9 @@ const char* CONFIGS[] = { " \"id\": 10," " \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ],\n" " \"interface\": \"eth0\",\n" + " \"reservations-global\": false,\n" " \"reservations-in-subnet\": true,\n" + " \"reservations-out-of-pool\": false,\n" " \"reservations\": [ \n" " {\n" " \"hw-address\": \"aa:bb:cc:dd:ee:ff\",\n" @@ -184,6 +193,8 @@ const char* CONFIGS[] = { "}" "],\n" "\"reservations-global\": true,\n" + "\"reservations-in-subnet\": false,\n" + "\"reservations-out-of-pool\": false,\n" "\"valid-lifetime\": 600,\n" "\"reservations\": [ \n" "{\n" @@ -235,6 +246,8 @@ const char* CONFIGS[] = { "}" "],\n" "\"reservations-global\": true,\n" + "\"reservations-in-subnet\": false,\n" + "\"reservations-out-of-pool\": false,\n" "\"valid-lifetime\": 600,\n" "\"reservations\": [ \n" "{\n" @@ -340,7 +353,7 @@ const char* CONFIGS[] = { "}", // Configuration 8 both global and in-subnet - // 2 subnets, one reservations flags default (aka in-subnet), + // 2 subnets, one default reservations flags (aka in-subnet), // one reservations flags global and in-subnet. // Host reservations for the same client, one global, one in each subnet "{ \"interfaces-config\": {\n" @@ -372,6 +385,7 @@ const char* CONFIGS[] = { " \"interface\": \"eth1\",\n" " \"reservations-global\": true,\n" " \"reservations-in-subnet\": true,\n" + " \"reservations-out-of-pool\": false,\n" " \"reservations\": [ \n" " {\n" " \"hw-address\": \"aa:bb:cc:dd:ee:ff\",\n" @@ -556,7 +570,8 @@ public: }; // Verifies that a client, which fails to match to a global -// reservation, still gets a dynamic address when subnet mode is HR_GLOBAL +// reservation, still gets a dynamic address when subnet reservations +// flags are global only. TEST_F(HostTest, globalHardwareNoMatch) { Dhcp4Client client(Dhcp4Client::SELECTING); @@ -566,7 +581,7 @@ TEST_F(HostTest, globalHardwareNoMatch) { // Verifies that a client, that matches to a global hostname // reservation, gets both the hostname and a dynamic address, -// when the subnet mode is HR_GLOBAL +// when the subnet reservations flags are global only. TEST_F(HostTest, globalHardwareDynamicAddress) { Dhcp4Client client(Dhcp4Client::SELECTING); @@ -576,7 +591,7 @@ TEST_F(HostTest, globalHardwareDynamicAddress) { // Verifies that a client matched to a global address reservation // gets both the hostname and the reserved address -// when the subnet mode is HR_GLOBAL +// when the subnet reservations flags are global only. TEST_F(HostTest, globalHardwareFixedAddress) { Dhcp4Client client(Dhcp4Client::SELECTING); @@ -632,22 +647,22 @@ TEST_F(HostTest, globalClientID) { // Verifies that even when a matching global reservation exists, // client will get a subnet scoped reservation, when subnet -// reservation mode is default +// reservations flags are default TEST_F(HostTest, defaultOverGlobal) { Dhcp4Client client(Dhcp4Client::SELECTING); // Hardware address matches all reservations client.setHWAddress("aa:bb:cc:dd:ee:ff"); - // Subnet 10 usses default HR mode(i.e. "in-pool"), so its + // Subnet 10 uses default reservations flags (i.e. in-subnet), so its // reservation should be used, rather than global. runDoraTest(CONFIGS[1], client, "subnet-10-host", "10.0.0.10"); } // Verifies that when there are matching reservations at // both the global and subnet levels, client will be matched -// to the global reservation, when subnet reservation mode -// is HR_GLOBAL. +// to the global reservation, when subnet reservations flags +// are global only. TEST_F(HostTest, globalOverSubnet) { Dhcp4Client client(Dhcp4Client::SELECTING); @@ -658,44 +673,44 @@ TEST_F(HostTest, globalOverSubnet) { client.setIfaceName("eth1"); client.setIfaceIndex(ETH1_INDEX); - // Subnet 20 usses global HR mode, so the global + // Subnet 20 uses global only reservations flags, so the global // reservation should be used, rather than the subnet one. runDoraTest(CONFIGS[1], client, "global-host", "192.0.2.10"); } // Verifies that when there are matching reservations at // both the global and subnet levels, client will be matched -// to the subnet reservation, when subnet reservation mode -// is HR_OUT_OF_POOL +// to the subnet reservation, when subnet reservations flags +// are in-subnet and out-of-pool. TEST_F(HostTest, outOfPoolOverGlobal) { Dhcp4Client client(Dhcp4Client::SELECTING); // Hardware address matches all reservations client.setHWAddress("aa:bb:cc:dd:ee:ff"); - // Subnet 10 uses "out-of-pool" HR mode, so its - // reservation should be used, rather than global. + // Subnet 10 uses in-subnet and out-of-pool reservations flags, + // so its reservation should be used, rather than global. runDoraTest(CONFIGS[2], client, "subnet-10-host", "10.0.0.105"); } // Verifies that when there are matching reservations at // both the global and subnet levels, client will be matched -// to the subnet reservation, when subnet reservation mode -// is HR_ALL +// to the subnet reservation, when subnet reservations flags +// are in-subnet only. TEST_F(HostTest, allOverGlobal) { Dhcp4Client client(Dhcp4Client::SELECTING); // Hardware address matches all reservations client.setHWAddress("aa:bb:cc:dd:ee:ff"); - // Subnet 10 uses default HR mode(i.e. "all"), so its + // Subnet 10 uses default reservations flags (i.e. in-subnet), so its // reservation should be used, rather than global. runDoraTest(CONFIGS[3], client, "subnet-10-host", "10.0.0.105"); } // Verifies that when there are matching reservations at // both the global and subnet levels, client will be matched -// to the subnet reservation, when subnet reservation true flags +// to the subnet reservation, when subnet reservations flags // are global and in-subnet, i.e. the subnet has the preference. TEST_F(HostTest, subnetOverGlobal) { Dhcp4Client client(Dhcp4Client::SELECTING); diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc index cb64425b67..f28255ae9d 100644 --- a/src/bin/dhcp6/dhcp6_srv.cc +++ b/src/bin/dhcp6/dhcp6_srv.cc @@ -4289,4 +4289,3 @@ Dhcpv6Srv::checkDynamicSubnetChange(const Pkt6Ptr& question, Pkt6Ptr& answer, } // namespace dhcp } // namespace isc - diff --git a/src/bin/dhcp6/tests/host_unittest.cc b/src/bin/dhcp6/tests/host_unittest.cc index feceada7a7..43b5a9b411 100644 --- a/src/bin/dhcp6/tests/host_unittest.cc +++ b/src/bin/dhcp6/tests/host_unittest.cc @@ -57,6 +57,7 @@ namespace { /// - Similar to Configuration 6, but one of the addresses reserved to client /// with the DUID 04:03:02:01. /// +/// Descriptions of next configurations are in the comment with the number. const char* CONFIGS[] = { // Configuration 0: "{ " @@ -350,12 +351,16 @@ const char* CONFIGS[] = { "\"mac-sources\": [ \"ipv6-link-local\" ], \n" "\"subnet6\": [ \n" " { \n" + " \"id\": 1, \n" " \"subnet\": \"2001:db8:1::/48\", \n" " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ], \n" " \"interface\" : \"eth0\", \n" - " \"reservations-global\": true\n" + " \"reservations-global\": true, \n" + " \"reservations-in-subnet\": false, \n" + " \"reservations-out-of-pool\": false \n" " }," " { \n" + " \"id\": 2, \n" " \"subnet\": \"2001:db8:2::/48\", \n" " \"pools\": [ { \"pool\": \"2001:db8:2::/64\" } ], \n" " \"interface\" : \"eth1\", \n" @@ -392,9 +397,12 @@ const char* CONFIGS[] = { "\"mac-sources\": [ \"ipv6-link-local\" ], \n" "\"subnet6\": [ \n" " { \n" + " \"id\": 1, \n" " \"subnet\": \"2001:db8:1::/48\", \n" " \"interface\" : \"eth0\", \n" - " \"reservations-global\": true,\n" + " \"reservations-global\": true, \n" + " \"reservations-in-subnet\": false, \n" + " \"reservations-out-of-pool\": false, \n" " \"pd-pools\": [ \n" " { \n" " \"prefix\": \"3000::\", \n" @@ -403,6 +411,7 @@ const char* CONFIGS[] = { " }] \n" " }," " { \n" + " \"id\": 2, \n" " \"subnet\": \"2001:db8:2::/48\", \n" " \"interface\" : \"eth1\", \n" " \"pd-pools\": [ \n" @@ -436,6 +445,8 @@ const char* CONFIGS[] = { "}" "],\n" "\"reservations-global\": true,\n" + "\"reservations-in-subnet\": false,\n" + "\"reservations-out-of-pool\": false,\n" "\"valid-lifetime\": 4000,\n" "\"reservations\": [ \n" "{\n" @@ -488,6 +499,8 @@ const char* CONFIGS[] = { "}" "],\n" "\"reservations-global\": true,\n" + "\"reservations-in-subnet\": false,\n" + "\"reservations-out-of-pool\": false,\n" "\"valid-lifetime\": 4000,\n" "\"reservations\": [ \n" "{\n" @@ -2383,7 +2396,7 @@ TEST_F(HostTest, globalReservationsNA) { } { - SCOPED_TRACE("Default subnet mode excludes Global HR"); + SCOPED_TRACE("Default subnet reservations flags excludes global reservations"); client.clearConfig(); client.setInterface("eth1"); client.setDUID("01:02:03:04"); @@ -2408,7 +2421,8 @@ TEST_F(HostTest, globalReservationsNA) { Subnet6Ptr subnet = CfgMgr::instance().getCurrentCfg()-> getCfgSubnets6()->getSubnet(2); ASSERT_TRUE(subnet); - subnet->setHostReservationMode(Network::HR_IN_SUBNET|Network::HR_GLOBAL); + subnet->setReservationsGlobal(true); + subnet->setReservationsInSubnet(true); client.clearConfig(); client.setInterface("eth1"); client.setDUID("01:02:03:05"); @@ -2445,7 +2459,7 @@ TEST_F(HostTest, globalReservationsPD) { } { - SCOPED_TRACE("Default subnet mode excludes Global HR"); + SCOPED_TRACE("Default subnet reservations flags excludes global reservations"); client.clearConfig(); client.setInterface("eth1"); client.setDUID("01:02:03:04"); @@ -2470,7 +2484,8 @@ TEST_F(HostTest, globalReservationsPD) { Subnet6Ptr subnet = CfgMgr::instance().getCurrentCfg()-> getCfgSubnets6()->getSubnet(2); ASSERT_TRUE(subnet); - subnet->setHostReservationMode(Network::HR_IN_SUBNET|Network::HR_GLOBAL); + subnet->setReservationsGlobal(true); + subnet->setReservationsInSubnet(true); client.clearConfig(); client.setInterface("eth1"); client.setDUID("01:02:03:05"); diff --git a/src/bin/keactrl/kea-dhcp4.conf.pre b/src/bin/keactrl/kea-dhcp4.conf.pre index b96a2f7d38..5b162b8072 100644 --- a/src/bin/keactrl/kea-dhcp4.conf.pre +++ b/src/bin/keactrl/kea-dhcp4.conf.pre @@ -360,9 +360,9 @@ // specific options. // // When using reservations, it is useful to configure - // reservations-out-of-pool, reservations-in-subnet, - // reservations-global (subnet specific parameters) and - // host-reservation-identifiers (global parameter). + // reservations-global, reservations-in-subnet, + // reservations-out-of-pool (subnet specific parameters) + // and host-reservation-identifiers (global parameter). { "client-id": "01:12:23:34:45:56:67", "ip-address": "192.0.2.204", diff --git a/src/lib/dhcpsrv/Makefile.am b/src/lib/dhcpsrv/Makefile.am index 9dee7779d1..0f7a8bb554 100644 --- a/src/lib/dhcpsrv/Makefile.am +++ b/src/lib/dhcpsrv/Makefile.am @@ -45,8 +45,6 @@ EXTRA_DIST += parsers/ifaces_config_parser.h EXTRA_DIST += parsers/multi_threading_config_parser.cc EXTRA_DIST += parsers/multi_threading_config_parser.h EXTRA_DIST += parsers/option_data_parser.h -EXTRA_DIST += parsers/reservation_modes_parser.cc -EXTRA_DIST += parsers/reservation_modes_parser.h EXTRA_DIST += parsers/sanity_checks_parser.cc EXTRA_DIST += parsers/sanity_checks_parser.h EXTRA_DIST += parsers/simple_parser4.cc @@ -180,8 +178,6 @@ libkea_dhcpsrv_la_SOURCES += parsers/option_data_parser.cc libkea_dhcpsrv_la_SOURCES += parsers/option_data_parser.h libkea_dhcpsrv_la_SOURCES += parsers/dhcp_queue_control_parser.cc libkea_dhcpsrv_la_SOURCES += parsers/dhcp_queue_control_parser.h -libkea_dhcpsrv_la_SOURCES += parsers/reservation_modes_parser.cc -libkea_dhcpsrv_la_SOURCES += parsers/reservation_modes_parser.h libkea_dhcpsrv_la_SOURCES += parsers/sanity_checks_parser.cc libkea_dhcpsrv_la_SOURCES += parsers/sanity_checks_parser.h libkea_dhcpsrv_la_SOURCES += parsers/shared_network_parser.cc @@ -412,7 +408,6 @@ libkea_dhcpsrv_parsers_include_HEADERS = \ parsers/multi_threading_config_parser.h \ parsers/option_data_parser.h \ parsers/dhcp_queue_control_parser.h \ - parsers/reservation_modes_parser.h \ parsers/sanity_checks_parser.h \ parsers/shared_network_parser.h \ parsers/shared_networks_list_parser.h \ diff --git a/src/lib/dhcpsrv/alloc_engine.h b/src/lib/dhcpsrv/alloc_engine.h index b7c85fdb02..4faee11e61 100644 --- a/src/lib/dhcpsrv/alloc_engine.h +++ b/src/lib/dhcpsrv/alloc_engine.h @@ -651,12 +651,15 @@ public: /// @brief Returns host from the most preferred subnet. /// + /// If there is no such host and global reservations are enabled + /// returns the global host. + /// /// @return Pointer to the host object. ConstHostPtr currentHost() const; /// @brief Returns global host reservation if there is one /// - /// If the current subnet's reservation mode is global and + /// If the current subnet's reservations-global is true and /// there is a global host (i.e. reservation belonging to /// the global subnet), return it. Otherwise return an /// empty pointer. @@ -666,8 +669,8 @@ public: /// @brief Determines if a global reservation exists /// - /// @return true if there current subnet's reservation mode is - /// global and there is global host containing the given + /// @return true if there current subnet's reservations-global + /// is true and there is global host containing the given /// lease reservation, false otherwise bool hasGlobalReservation(const IPv6Resrv& resv) const; @@ -1024,14 +1027,13 @@ private: /// @brief Creates new leases based on reservations. /// - /// This method allcoates new leases, based on host reservations. - /// Existing leases are specified in the existing_leases parameter. - /// It first calls @c allocateGlobalReservedLeases6 to accomodate - /// subnets using global reservations. If that method allocates - /// addresses, we return, otherwise we continue and check for non-global - /// reservations. A new lease is not created, if there is a lease for - /// specified address on existing_leases list or there is a lease used by - /// someone else. + /// This method allocates new leases, based on host reservations. + /// Existing leases are specified in the existing_leases + /// parameter. It first checks for non-global reservations. A + /// new lease is not created, if there is a lease for specified + /// address on existing_leases list or there is a lease used by + /// someone else. It last calls @c allocateGlobalReservedLeases6 + /// to accomodate subnets using global reservations. /// /// @param ctx client context that contains all details (subnet, client-id, etc.) /// @param existing_leases leases that are already associated with the client @@ -1407,12 +1409,15 @@ public: /// @brief Returns host for currently selected subnet. /// + /// If there is no such host and global reservations are enabled + /// returns the global host. + /// /// @return Pointer to the host object. ConstHostPtr currentHost() const; /// @brief Returns global host reservation if there is one /// - /// If the current subnet's reservation mode is global and + /// If the current subnet's reservations-global is true and /// there is a global host (i.e. reservation belonging to /// the global subnet), return it. Otherwise return an /// empty pointer. diff --git a/src/lib/dhcpsrv/network.cc b/src/lib/dhcpsrv/network.cc index a0268d7564..c964fc8ae4 100644 --- a/src/lib/dhcpsrv/network.cc +++ b/src/lib/dhcpsrv/network.cc @@ -19,15 +19,6 @@ using namespace isc::util; namespace isc { namespace dhcp { -const uint8_t Network::HR_DISABLED = 0; -const uint8_t Network::HR_OUT_OF_POOL_FLAG = 1 << 0; -const uint8_t Network::HR_IN_SUBNET_FLAG = 1 << 1; -const uint8_t Network::HR_GLOBAL_FLAG = 1 << 2; -const uint8_t Network::HR_OUT_OF_POOL = HR_OUT_OF_POOL_FLAG | HR_IN_SUBNET_FLAG; -const uint8_t Network::HR_IN_SUBNET = HR_IN_SUBNET_FLAG; -const uint8_t Network::HR_GLOBAL = HR_GLOBAL_FLAG; -const uint8_t Network::HR_ALL = Network::HR_IN_SUBNET; - void Network::RelayInfo::addAddress(const asiolink::IOAddress& addr) { if (containsAddress(addr)) { @@ -108,24 +99,6 @@ Network::getRequiredClasses() const { return (required_classes_); } -Network::HRMode -Network::hrModeFromString(const std::string& hr_mode_name) { - if ( (hr_mode_name.compare("disabled") == 0) || - (hr_mode_name.compare("off") == 0) ) { - return (Network::HR_DISABLED); - } else if (hr_mode_name.compare("out-of-pool") == 0) { - return (Network::HR_OUT_OF_POOL); - } else if (hr_mode_name.compare("global") == 0) { - return (Network::HR_GLOBAL); - } else if (hr_mode_name.compare("all") == 0) { - return (Network::HR_ALL); - } else { - // Should never happen... - isc_throw(BadValue, "Can't convert '" << hr_mode_name - << "' into any valid reservation-mode values"); - } -} - Optional Network::getGlobalProperty(Optional property, const std::string& global_name) const { @@ -210,36 +183,22 @@ Network::toElement() const { } } - // Set reservation mode - Optional hrmode = host_reservation_mode_; - if (!hrmode.unspecified()) { - bool hr_global = false; - bool hr_in_subnet = false; - bool hr_out_of_pool = false; - if (hrmode & Network::HR_GLOBAL) { - hr_global = true; - } - if (hrmode & Network::HR_IN_SUBNET_FLAG) { - hr_in_subnet = true; - } - if (hrmode & Network::HR_OUT_OF_POOL_FLAG) { - hr_out_of_pool = true; - } - if (hrmode == Network::HR_DISABLED) { - map->set("reservations-global", Element::create(false)); - map->set("reservations-in-subnet", Element::create(false)); - map->set("reservations-out-of-pool", Element::create(false)); - } else { - if (hr_global) { - map->set("reservations-global", Element::create(true)); - } - if (hr_in_subnet) { - map->set("reservations-in-subnet", Element::create(true)); - } - if (hr_out_of_pool) { - map->set("reservations-out-of-pool", Element::create(true)); - } - } + // Set reservations-global + if (!reservations_global_.unspecified()) { + map->set("reservations-global", + Element::create(reservations_global_.get())); + } + + // Set reservations-in-subnet + if (!reservations_in_subnet_.unspecified()) { + map->set("reservations-in-subnet", + Element::create(reservations_in_subnet_.get())); + } + + // Set reservations-out-of-pool + if (!reservations_out_of_pool_.unspecified()) { + map->set("reservations-out-of-pool", + Element::create(reservations_out_of_pool_.get())); } // Set options diff --git a/src/lib/dhcpsrv/network.h b/src/lib/dhcpsrv/network.h index 66aa7b0e7c..4fdd85c306 100644 --- a/src/lib/dhcpsrv/network.h +++ b/src/lib/dhcpsrv/network.h @@ -152,48 +152,6 @@ public: IOAddressList addresses_; }; - /// @brief Specifies allowed host reservation mode. - /// - /// None - host reservation is disabled. No reservation types - /// are allowed. - static const uint8_t HR_DISABLED; // value: 0 - - /// The out-of-pool reservations flag. - static const uint8_t HR_OUT_OF_POOL_FLAG; // value: 1 << 0 - - /// The in-subnet flag. - static const uint8_t HR_IN_SUBNET_FLAG; // value: 1 << 1 - - /// The global flag. - static const uint8_t HR_GLOBAL_FLAG; // value: 1 << 2 - - /// Only out-of-pool reservations is allowed. This mode allows AllocEngine - /// to skip reservation checks for dynamically allocated addressed. - /// When this is set, both HR_OUT_OF_POOL_FLAG and HR_IN_SUBNET_FLAG are - /// enabled as there can can be no reservations that are out-of-pool but not - /// in-subnet. - static const uint8_t HR_OUT_OF_POOL; // value: HR_OUT_OF_POOL_FLAG | HR_IN_SUBNET_FLAG - - /// The in-subnet mode which also allows in-pool reservations. - /// This is equivalent to HR_ALL flag. - static const uint8_t HR_IN_SUBNET; // value: HR_IN_SUBNET_FLAG - - /// Only global reservations are allowed. This mode instructs AllocEngine - /// to only look at global reservations. - static const uint8_t HR_GLOBAL; // value: HR_GLOBAL_FLAG - - /// Both out-of-pool and in-pool reservations are allowed. This is the most - /// flexible mode, where sysadmin have biggest liberty. However, there is a - /// non-trivial performance penalty for it, as the AllocEngine code has to - /// check whether there are reservations, even when dealing with - /// reservations from within the dynamic pools. This is required so that the - /// dynamically allocated addresses don't match any of the reservations. - /// This is the default mode. - static const uint8_t HR_ALL; // value: HR_IN_SUBNET - - /// @brief Bitset used to store @ref HRModeFlag flags. - typedef uint8_t HRMode; - /// @brief Inheritance "mode" used when fetching an optional @c Network /// parameter. /// @@ -218,7 +176,8 @@ public: /// @brief Constructor. Network() : iface_name_(), client_class_(), t1_(), t2_(), valid_(), - host_reservation_mode_(HR_ALL, true), cfg_option_(new CfgOption()), + reservations_global_(false, true), reservations_in_subnet_(true, true), + reservations_out_of_pool_(false, true), cfg_option_(new CfgOption()), calculate_tee_times_(), t1_percent_(), t2_percent_(), ddns_send_updates_(), ddns_override_no_update_(), ddns_override_client_update_(), ddns_replace_client_name_mode_(), ddns_generated_prefix_(), ddns_qualifying_suffix_(), @@ -412,105 +371,59 @@ public: t2_ = t2; } - /// @brief Specifies what type of Host Reservations are supported. - /// - /// Host reservations may be any of the combinations of in-subnet (they - /// reserve an address that is in the subnet either in-pool or out-of-pool), - /// out-of-pool (they reserve an address that is in-subnet but not in-pool) - /// or global (they are defined at global level). HR may also be completely - /// disabled for performance reasons. + /// @brief Returns whether global reservations should be fetched. /// /// @param inheritance inheritance mode to be used. - /// @return Host reservation mode enabled. - util::Optional - getHostReservationMode(const Inheritance& inheritance = Inheritance::ALL) const { - // Inheritance for host reservations is a little different than for other - // parameters. The reservation at the global level is given as a string. - // Thus we call getProperty here without a global name to check if the - // host reservation mode is specified on network level only. - const util::Optional& hr_mode = getProperty(&Network::getHostReservationMode, - host_reservation_mode_, - inheritance); - // If HR mode is not specified at network level we need this special - // case code to handle conversion of the globally configured HR - // mode to an enum. - if (hr_mode.unspecified() && (inheritance != Inheritance::NONE) && - (inheritance != Inheritance::PARENT_NETWORK)) { - // Get global reservation mode. - util::Optional hr_mode_name; - hr_mode_name = getGlobalProperty(hr_mode_name, "reservation-mode"); - if (!hr_mode_name.unspecified()) { - try { - // If the HR mode is globally configured, let's convert it from - // a string to enum. - return (hrModeFromString(hr_mode_name.get())); - - } catch (...) { - // This should not really happen because the configuration - // parser should have already verified the globally configured - // reservation mode. However, we want to be 100% sure that this - // method doesn't throw. Let's just return unspecified. - return (hr_mode); - } - } else { - // Get global reservation modes and merge the values. - bool found = false; - uint8_t flags = 0; - util::Optional hr_mode_global; - hr_mode_global = getGlobalProperty(hr_mode_global, - "reservations-global"); - if (!hr_mode_global.unspecified()) { - if (hr_mode_global.get()) { - flags |= Network::HR_GLOBAL; - } - found = true; - } - util::Optional hr_mode_in_subnet; - hr_mode_in_subnet = getGlobalProperty(hr_mode_in_subnet, - "reservations-in-subnet"); - if (!hr_mode_in_subnet.unspecified()) { - if (hr_mode_in_subnet.get()) { - flags |= Network::HR_IN_SUBNET; - } - found = true; - } - util::Optional hr_mode_out_of_pool; - hr_mode_out_of_pool = getGlobalProperty(hr_mode_out_of_pool, - "reservations-out-of-pool"); - if (!hr_mode_out_of_pool.unspecified()) { - if (hr_mode_out_of_pool.get()) { - flags |= Network::HR_OUT_OF_POOL; - } - found = true; - } - if (found) { - return (static_cast(flags)); - } - } - } - return (hr_mode); + util::Optional + getReservationsGlobal(const Inheritance& inheritance = Inheritance::ALL) const { + return (getProperty(&Network::getReservationsGlobal, + reservations_global_, + inheritance, + "reservations-global")); } - /// @brief Sets host reservation mode. + /// @brief Sets whether global reservations should be fetched. /// - /// See @ref getHostReservationMode for details. - /// - /// @param mode mode to be set - void setHostReservationMode(const util::Optional& mode) { - host_reservation_mode_ = mode; + /// @param reservations_global new value of enabled/disabled. + void setReservationsGlobal(const util::Optional& reservations_global) { + reservations_global_ = reservations_global; } - /// @brief Attempts to convert text representation to HRMode enum. + /// @brief Returns whether subnet reservations should be fetched. /// - /// Allowed values are "disabled", "off" (alias for disabled), - /// "out-of-pool" and "all". See @c Network::HRMode for their exact meaning. + /// @param inheritance inheritance mode to be used. + util::Optional + getReservationsInSubnet(const Inheritance& inheritance = Inheritance::ALL) const { + return (getProperty(&Network::getReservationsInSubnet, + reservations_in_subnet_, + inheritance, + "reservations-in-subnet")); + } + + /// @brief Sets whether subnet reservations should be fetched. /// - /// @param hr_mode_name Host Reservation mode in the textual form. + /// @param reservations_in_subnet new value of enabled/disabled. + void setReservationsInSubnet(const util::Optional& reservations_in_subnet) { + reservations_in_subnet_ = reservations_in_subnet; + } + + /// @brief Returns whether only out-of-pool reservations are allowed. /// - /// @throw BadValue if the text cannot be converted. + /// @param inheritance inheritance mode to be used. + util::Optional + getReservationsOutOfPool(const Inheritance& inheritance = Inheritance::ALL) const { + return (getProperty(&Network::getReservationsOutOfPool, + reservations_out_of_pool_, + inheritance, + "reservations-out-of-pool")); + } + + /// @brief Sets whether only out-of-pool reservations are allowed. /// - /// @return one of allowed HRMode values - static HRMode hrModeFromString(const std::string& hr_mode_name); + /// @param reservations_out_of_pool new value of enabled/disabled. + void setReservationsOutOfPool(const util::Optional& reservations_out_of_pool) { + reservations_out_of_pool_ = reservations_out_of_pool; + } /// @brief Returns pointer to the option data configuration for this network. CfgOptionPtr getCfgOption() { @@ -651,7 +564,7 @@ public: } catch (...) { // This should not really happen because the configuration // parser should have already verified the globally configured - // reservation mode. However, we want to be 100% sure that this + // mode. However, we want to be 100% sure that this // method doesn't throw. Let's just return unspecified. return (mode); } @@ -840,8 +753,8 @@ protected: /// name. Typically, this method is invoked by @c getProperty when /// network specific value of the parameter is not found. In some cases /// it may be called by other methods. One such example is the - /// @c getHostReservationMode which needs to call @c getGlobalProperty - /// explicitly to convert the global host reservation mode value from + /// @c getDdnsReplaceClientNameMode which needs to call @c getGlobalProperty + /// explicitly to convert the global replace client name mode value from /// a string to an enum. /// /// @tparam ReturnType Type of the returned value, e.g. @@ -1062,10 +975,18 @@ protected: /// @brief a Triplet (min/default/max) holding allowed valid lifetime values Triplet valid_; - /// @brief Specifies host reservation mode + /// @brief Enables global reservations. + util::Optional reservations_global_; + + /// @brief Enables subnet reservations. + util::Optional reservations_in_subnet_; + + /// @brief Enables out-of-pool reservations optimization. /// - /// See @ref HRMode type for details. - util::Optional host_reservation_mode_; + /// When true only out-of-pool reservations are allowed. This allows + /// AllocEngine to skip reservation checks when dealing with addresses + /// that are in pool. + util::Optional reservations_out_of_pool_; /// @brief Pointer to the option data configuration for this subnet. CfgOptionPtr cfg_option_; @@ -1117,7 +1038,7 @@ protected: /// @brief Value in seconds to use as cache maximal age. util::Optional cache_max_age_; - /// @brief Should Kea perform updates when leases are extended + /// @brief Should Kea perform updates when leases are extended util::Optional ddns_update_on_renew_; /// @brief Used to to tell kea-dhcp-ddns whether or not to use conflict resolution. diff --git a/src/lib/dhcpsrv/parsers/reservation_modes_parser.cc b/src/lib/dhcpsrv/parsers/reservation_modes_parser.cc deleted file mode 100644 index 30c3fb47cf..0000000000 --- a/src/lib/dhcpsrv/parsers/reservation_modes_parser.cc +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (C) 2015-2020 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 -#include -#include -#include -#include - -#include -#include - -using namespace isc::data; -using namespace isc::util; - -namespace isc { -namespace dhcp { - -Network::HRMode -HostReservationModesParser::parse(const ConstElementPtr& config_elem) { - if (config_elem->getType() != Element::map) { - isc_throw(DhcpConfigError, "configuration must be a map"); - } - - ConstElementPtr elem; - uint8_t flags = 0; - bool force_true = false; - - try { - elem = config_elem->get("reservations-out-of-pool"); - if (elem) { - bool value = elem->boolValue(); - if (value) { - flags |= Network::HR_OUT_OF_POOL; - force_true = true; - } - } - - elem = config_elem->get("reservations-in-subnet"); - if (elem) { - bool value = elem->boolValue(); - if (value) { - flags |= Network::HR_IN_SUBNET; - } else if (force_true) { - isc_throw(DhcpConfigError, "invalid use of disabled 'reservations-in-subnet'" - " when enabled 'reservations-out-of-pool'"); - } - } - - elem = config_elem->get("reservations-global"); - if (elem) { - bool value = elem->boolValue(); - if (value) { - flags |= Network::HR_GLOBAL; - } - } - } catch (const Exception& ex) { - isc_throw(DhcpConfigError, "error parsing element: " << ex.what()); - } - - return (static_cast(flags)); -} - -} // end of namespace isc::dhcp -} // end of namespace isc diff --git a/src/lib/dhcpsrv/parsers/reservation_modes_parser.h b/src/lib/dhcpsrv/parsers/reservation_modes_parser.h deleted file mode 100644 index e1dddb1f2f..0000000000 --- a/src/lib/dhcpsrv/parsers/reservation_modes_parser.h +++ /dev/null @@ -1,42 +0,0 @@ -// 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 RESERVATION_MODES_PARSER_H -#define RESERVATION_MODES_PARSER_H - -#include -#include -#include -#include - -namespace isc { -namespace dhcp { - -/// @brief Parser for the configuration of DHCP packet queue controls -/// -/// This parser parses the "reservation-modes" parameter which holds the -/// the configurable parameters that tailor host reservation modes. -/// -/// This parser is used in both DHCPv4 and DHCPv6, and also inside subnet and -/// shared networks. -class HostReservationModesParser : public isc::data::SimpleParser { -public: - - /// @brief Parses content of the "reservation-modes". - /// - /// @param control_elem MapElement containing the host reservation modes - /// values to parse - /// - /// @return Host reservation modes flags. - /// - /// @throw DhcpConfigError if any of the values are invalid. - Network::HRMode parse(const isc::data::ConstElementPtr& control_elem); -}; - -} -} // end of namespace isc - -#endif // RESERVATION_MODES_PARSER_H diff --git a/src/lib/dhcpsrv/parsers/simple_parser4.cc b/src/lib/dhcpsrv/parsers/simple_parser4.cc index 87944e74d9..48d4a3efbd 100644 --- a/src/lib/dhcpsrv/parsers/simple_parser4.cc +++ b/src/lib/dhcpsrv/parsers/simple_parser4.cc @@ -71,9 +71,9 @@ const SimpleKeywords SimpleParser4::GLOBAL4_PARAMETERS = { { "config-control", Element::map }, { "server-tag", Element::string }, { "reservation-mode", Element::string }, - { "reservations-out-of-pool", Element::boolean }, - { "reservations-in-subnet", Element::boolean }, { "reservations-global", Element::boolean }, + { "reservations-in-subnet", Element::boolean }, + { "reservations-out-of-pool", Element::boolean }, { "calculate-tee-times", Element::boolean }, { "t1-percent", Element::real }, { "t2-percent", Element::real }, @@ -113,9 +113,9 @@ const SimpleDefaults SimpleParser4::GLOBAL4_DEFAULTS = { { "server-hostname", Element::string, "" }, { "boot-file-name", Element::string, "" }, { "server-tag", Element::string, "" }, - { "reservations-out-of-pool", Element::boolean, "false" }, - { "reservations-in-subnet", Element::boolean, "true" }, { "reservations-global", Element::boolean, "false" }, + { "reservations-in-subnet", Element::boolean, "true" }, + { "reservations-out-of-pool", Element::boolean, "false" }, { "calculate-tee-times", Element::boolean, "false" }, { "t1-percent", Element::real, ".50" }, { "t2-percent", Element::real, ".875" }, @@ -212,9 +212,9 @@ const SimpleKeywords SimpleParser4::SUBNET4_PARAMETERS = { { "require-client-classes", Element::list }, { "reservations", Element::list }, { "reservation-mode", Element::string }, - { "reservations-out-of-pool", Element::boolean }, - { "reservations-in-subnet", Element::boolean }, { "reservations-global", Element::boolean }, + { "reservations-in-subnet", Element::boolean }, + { "reservations-out-of-pool", Element::boolean }, { "relay", Element::map }, { "match-client-id", Element::boolean }, { "authoritative", Element::boolean }, @@ -332,9 +332,9 @@ const SimpleKeywords SimpleParser4::SHARED_NETWORK4_PARAMETERS = { { "boot-file-name", Element::string }, { "relay", Element::map }, { "reservation-mode", Element::string }, - { "reservations-out-of-pool", Element::boolean }, - { "reservations-in-subnet", Element::boolean }, { "reservations-global", Element::boolean }, + { "reservations-in-subnet", Element::boolean }, + { "reservations-out-of-pool", Element::boolean }, { "client-class", Element::string }, { "require-client-classes", Element::list }, { "valid-lifetime", Element::integer }, diff --git a/src/lib/dhcpsrv/parsers/simple_parser6.cc b/src/lib/dhcpsrv/parsers/simple_parser6.cc index a8ccdad620..7b71508292 100644 --- a/src/lib/dhcpsrv/parsers/simple_parser6.cc +++ b/src/lib/dhcpsrv/parsers/simple_parser6.cc @@ -72,9 +72,9 @@ const SimpleKeywords SimpleParser6::GLOBAL6_PARAMETERS = { { "config-control", Element::map }, { "server-tag", Element::string }, { "reservation-mode", Element::string }, - { "reservations-out-of-pool", Element::boolean }, - { "reservations-in-subnet", Element::boolean }, { "reservations-global", Element::boolean }, + { "reservations-in-subnet", Element::boolean }, + { "reservations-out-of-pool", Element::boolean }, { "calculate-tee-times", Element::boolean }, { "t1-percent", Element::real }, { "t2-percent", Element::real }, @@ -109,9 +109,9 @@ const SimpleDefaults SimpleParser6::GLOBAL6_DEFAULTS = { { "decline-probation-period", Element::integer, "86400" }, // 24h { "dhcp4o6-port", Element::integer, "0" }, { "server-tag", Element::string, "" }, - { "reservations-out-of-pool", Element::boolean, "false" }, - { "reservations-in-subnet", Element::boolean, "true" }, { "reservations-global", Element::boolean, "false" }, + { "reservations-in-subnet", Element::boolean, "true" }, + { "reservations-out-of-pool", Element::boolean, "false" }, { "calculate-tee-times", Element::boolean, "true" }, { "t1-percent", Element::real, ".50" }, { "t2-percent", Element::real, ".80" }, @@ -214,9 +214,9 @@ const SimpleKeywords SimpleParser6::SUBNET6_PARAMETERS = { { "require-client-classes", Element::list }, { "reservations", Element::list }, { "reservation-mode", Element::string }, - { "reservations-out-of-pool", Element::boolean }, - { "reservations-in-subnet", Element::boolean }, { "reservations-global", Element::boolean }, + { "reservations-in-subnet", Element::boolean }, + { "reservations-out-of-pool", Element::boolean }, { "relay", Element::map }, { "user-context", Element::map }, { "comment", Element::string }, @@ -341,9 +341,9 @@ const SimpleKeywords SimpleParser6::SHARED_NETWORK6_PARAMETERS = { { "option-data", Element::list }, { "relay", Element::map }, { "reservation-mode", Element::string }, - { "reservations-out-of-pool", Element::boolean }, - { "reservations-in-subnet", Element::boolean }, { "reservations-global", Element::boolean }, + { "reservations-in-subnet", Element::boolean }, + { "reservations-out-of-pool", Element::boolean }, { "client-class", Element::string }, { "require-client-classes", Element::list }, { "preferred-lifetime", Element::integer }, diff --git a/src/lib/dhcpsrv/tests/Makefile.am b/src/lib/dhcpsrv/tests/Makefile.am index 8b045e408b..8aad886da0 100644 --- a/src/lib/dhcpsrv/tests/Makefile.am +++ b/src/lib/dhcpsrv/tests/Makefile.am @@ -87,7 +87,6 @@ libdhcpsrv_unittests_SOURCES += csv_lease_file6_unittest.cc libdhcpsrv_unittests_SOURCES += d2_client_unittest.cc libdhcpsrv_unittests_SOURCES += d2_udp_unittest.cc libdhcpsrv_unittests_SOURCES += dhcp_queue_control_parser_unittest.cc -libdhcpsrv_unittests_SOURCES += reservation_modes_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 diff --git a/src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc index 1868799e41..6adc4f27c7 100644 --- a/src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc +++ b/src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc @@ -2899,13 +2899,13 @@ TEST_F(AllocEngine4Test, findReservation) { EXPECT_TRUE(ctx.currentHost()); EXPECT_EQ(ctx.currentHost()->getIPv4Reservation(), host->getIPv4Reservation()); - // It shouldn't be returned when HR_DISABLED mode is enabled. - subnet_->setHostReservationMode(Network::HR_DISABLED); + // It shouldn't be returned when reservations-in-subnet is disabled. + subnet_->setReservationsInSubnet(false); ASSERT_NO_THROW(engine.findReservation(ctx)); EXPECT_FALSE(ctx.currentHost()); // Check the out of the pool reservation mode. - subnet_->setHostReservationMode(Network::HR_OUT_OF_POOL); + subnet_->setReservationsOutOfPool(true); ASSERT_NO_THROW(engine.findReservation(ctx)); EXPECT_TRUE(ctx.currentHost()); EXPECT_EQ(ctx.currentHost()->getIPv4Reservation(), host->getIPv4Reservation()); @@ -3092,7 +3092,7 @@ TEST_F(AllocEngine4Test, globalReservationReservedAddressDiscover) { AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 0, false); - subnet_->setHostReservationMode(Network::HR_GLOBAL); + subnet_->setReservationsGlobal(true); // Query allocation engine for the lease to be assigned to this // client without specifying the address to be assigned. @@ -3140,7 +3140,7 @@ TEST_F(AllocEngine4Test, globalReservationReservedAddressRequest) { AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 0, false); - subnet_->setHostReservationMode(Network::HR_GLOBAL); + subnet_->setReservationsGlobal(true); // Query allocation engine for the lease to be assigned to this // client without specifying the address to be assigned. @@ -3192,7 +3192,7 @@ TEST_F(AllocEngine4Test, globalReservationDynamicDiscover) { AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 0, false); - subnet_->setHostReservationMode(Network::HR_GLOBAL); + subnet_->setReservationsGlobal(true); // Query allocation engine for the lease to be assigned to this // client without specifying the address to be assigned. @@ -3241,7 +3241,7 @@ TEST_F(AllocEngine4Test, globalReservationDynamicRequest) { AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 0, false); - subnet_->setHostReservationMode(Network::HR_GLOBAL); + subnet_->setReservationsGlobal(true); // Query allocation engine for the lease to be assigned to this // client without specifying the address to be assigned. @@ -3293,7 +3293,8 @@ TEST_F(AllocEngine4Test, mixedReservationReservedAddressDiscover) { AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 0, false); - subnet_->setHostReservationMode(Network::HR_GLOBAL|Network::HR_IN_SUBNET); + subnet_->setReservationsGlobal(true); + subnet_->setReservationsInSubnet(true); // Query allocation engine for the lease to be assigned to this // client without specifying the address to be assigned. @@ -3342,7 +3343,8 @@ TEST_F(AllocEngine4Test, mixedReservationReservedAddressRequest) { AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 0, false); - subnet_->setHostReservationMode(Network::HR_GLOBAL|Network::HR_IN_SUBNET); + subnet_->setReservationsGlobal(true); + subnet_->setReservationsInSubnet(true); // Query allocation engine for the lease to be assigned to this // client without specifying the address to be assigned. @@ -3398,7 +3400,8 @@ TEST_F(AllocEngine4Test, bothReservationReservedAddressDiscover) { AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 0, false); - subnet_->setHostReservationMode(Network::HR_GLOBAL|Network::HR_IN_SUBNET); + subnet_->setReservationsGlobal(true); + subnet_->setReservationsInSubnet(true); // Query allocation engine for the lease to be assigned to this // client without specifying the address to be assigned. @@ -3451,7 +3454,8 @@ TEST_F(AllocEngine4Test, bothReservationReservedAddressRequest) { AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 0, false); - subnet_->setHostReservationMode(Network::HR_GLOBAL|Network::HR_IN_SUBNET); + subnet_->setReservationsGlobal(true); + subnet_->setReservationsInSubnet(true); // Query allocation engine for the lease to be assigned to this // client without specifying the address to be assigned. diff --git a/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc index 5e5f5bf04f..df2956e07c 100644 --- a/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc +++ b/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc @@ -3407,7 +3407,7 @@ TEST_F(AllocEngine6Test, hostDynamicAddress) { CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host); CfgMgr::instance().commit(); - subnet_->setHostReservationMode(Network::HR_ALL); + subnet_->setReservationsInSubnet(true); // Create context which will be used to try to allocate leases Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234)); @@ -3498,7 +3498,7 @@ TEST_F(AllocEngine6Test, globalHostDynamicAddress) { CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host); CfgMgr::instance().commit(); - subnet_->setHostReservationMode(Network::HR_GLOBAL); + subnet_->setReservationsGlobal(true); // Create context which will be used to try to allocate leases Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234)); @@ -3585,7 +3585,7 @@ TEST_F(AllocEngine6Test, globalHostReservedAddress) { CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host); CfgMgr::instance().commit(); - subnet_->setHostReservationMode(Network::HR_GLOBAL); + subnet_->setReservationsGlobal(true); // Create context which will be used to try to allocate leases Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234)); @@ -3649,7 +3649,7 @@ TEST_F(AllocEngine6Test, globalHostReservedPrefix) { CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host); CfgMgr::instance().commit(); - subnet_->setHostReservationMode(Network::HR_GLOBAL); + subnet_->setReservationsGlobal(true); // Create context which will be used to try to allocate leases Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234)); @@ -3717,7 +3717,8 @@ TEST_F(AllocEngine6Test, mixedHostReservedAddress) { CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host); CfgMgr::instance().commit(); - subnet_->setHostReservationMode(Network::HR_GLOBAL|Network::HR_IN_SUBNET); + subnet_->setReservationsGlobal(true); + subnet_->setReservationsInSubnet(true); // Create context which will be used to try to allocate leases Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234)); @@ -3781,7 +3782,8 @@ TEST_F(AllocEngine6Test, mixedHostReservedPrefix) { CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host); CfgMgr::instance().commit(); - subnet_->setHostReservationMode(Network::HR_GLOBAL|Network::HR_IN_SUBNET); + subnet_->setReservationsGlobal(true); + subnet_->setReservationsInSubnet(true); // Create context which will be used to try to allocate leases Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234)); @@ -3858,7 +3860,8 @@ TEST_F(AllocEngine6Test, bothHostReservedAddress) { CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host); CfgMgr::instance().commit(); - subnet_->setHostReservationMode(Network::HR_GLOBAL|Network::HR_IN_SUBNET); + subnet_->setReservationsGlobal(true); + subnet_->setReservationsInSubnet(true); // Create context which will be used to try to allocate leases Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234)); @@ -3931,7 +3934,8 @@ TEST_F(AllocEngine6Test, bothHostReservedPrefix) { CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host); CfgMgr::instance().commit(); - subnet_->setHostReservationMode(Network::HR_GLOBAL|Network::HR_IN_SUBNET); + subnet_->setReservationsGlobal(true); + subnet_->setReservationsInSubnet(true); // Create context which will be used to try to allocate leases Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234)); diff --git a/src/lib/dhcpsrv/tests/cfg_subnets4_unittest.cc b/src/lib/dhcpsrv/tests/cfg_subnets4_unittest.cc index fafdc7230d..bd07c450c9 100644 --- a/src/lib/dhcpsrv/tests/cfg_subnets4_unittest.cc +++ b/src/lib/dhcpsrv/tests/cfg_subnets4_unittest.cc @@ -1037,7 +1037,9 @@ TEST(CfgSubnets4Test, unparseSubnet) { subnet3->setCalculateTeeTimes(true); subnet3->setT1Percent(0.50); subnet3->setT2Percent(0.65); - subnet3->setHostReservationMode(Network::HR_ALL); + subnet3->setReservationsGlobal(false); + subnet3->setReservationsInSubnet(true); + subnet3->setReservationsOutOfPool(false); subnet3->setAuthoritative(false); subnet3->setMatchClientId(true); subnet3->setSiaddr(IOAddress("192.0.2.2")); @@ -1115,7 +1117,9 @@ TEST(CfgSubnets4Test, unparseSubnet) { " \"4o6-interface-id\": \"\",\n" " \"4o6-subnet\": \"\",\n" " \"authoritative\": false,\n" + " \"reservations-global\": false,\n" " \"reservations-in-subnet\": true,\n" + " \"reservations-out-of-pool\": false,\n" " \"option-data\": [ ],\n" " \"pools\": [ ]\n," " \"require-client-classes\": [ \"foo\", \"bar\" ],\n" @@ -1282,7 +1286,9 @@ TEST(CfgSubnets4Test, teeTimePercentValidation) { " \"boot-file-name\": \"\", \n" " \"client-class\": \"\", \n" " \"require-client-classes\": [] \n," - " \"reservations-in-subnet\": true,\n" + " \"reservations-global\": false, \n" + " \"reservations-in-subnet\": true, \n" + " \"reservations-out-of-pool\": false, \n" " \"4o6-interface\": \"\", \n" " \"4o6-interface-id\": \"\", \n" " \"4o6-subnet\": \"\" \n" @@ -1349,7 +1355,9 @@ TEST(CfgSubnets4Test, validLifetimeValidation) { " \"boot-file-name\": \"\", \n" " \"client-class\": \"\", \n" " \"require-client-classes\": [] \n," - " \"reservations-in-subnet\": true,\n" + " \"reservations-global\": false, \n" + " \"reservations-in-subnet\": true, \n" + " \"reservations-out-of-pool\": false, \n" " \"4o6-interface\": \"\", \n" " \"4o6-interface-id\": \"\", \n" " \"4o6-subnet\": \"\" \n" @@ -1591,7 +1599,9 @@ TEST(CfgSubnets4Test, hostnameSanitizierValidation) { " \"boot-file-name\": \"\", \n" " \"client-class\": \"\", \n" " \"require-client-classes\": [] \n," - " \"reservations-in-subnet\": true,\n" + " \"reservations-global\": false, \n" + " \"reservations-in-subnet\": true, \n" + " \"reservations-out-of-pool\": false, \n" " \"4o6-interface\": \"\", \n" " \"4o6-interface-id\": \"\", \n" " \"4o6-subnet\": \"\" \n" @@ -1669,7 +1679,9 @@ TEST(CfgSubnets4Test, cacheParamValidation) { " \"boot-file-name\": \"\", \n" " \"client-class\": \"\", \n" " \"require-client-classes\": [] \n," - " \"reservations-in-subnet\": true,\n" + " \"reservations-global\": false, \n" + " \"reservations-in-subnet\": true, \n" + " \"reservations-out-of-pool\": false, \n" " \"4o6-interface\": \"\", \n" " \"4o6-interface-id\": \"\", \n" " \"4o6-subnet\": \"\" \n" diff --git a/src/lib/dhcpsrv/tests/cfg_subnets6_unittest.cc b/src/lib/dhcpsrv/tests/cfg_subnets6_unittest.cc index ce57ebe1dd..a2c940b1da 100644 --- a/src/lib/dhcpsrv/tests/cfg_subnets6_unittest.cc +++ b/src/lib/dhcpsrv/tests/cfg_subnets6_unittest.cc @@ -637,7 +637,9 @@ TEST(CfgSubnets6Test, unparseSubnet) { subnet3->setIface("eth1"); subnet3->requireClientClass("foo"); subnet3->requireClientClass("bar"); - subnet3->setHostReservationMode(Network::HR_ALL); + subnet3->setReservationsGlobal(false); + subnet3->setReservationsInSubnet(true); + subnet3->setReservationsOutOfPool(false); subnet3->setRapidCommit(false); subnet3->setCalculateTeeTimes(true); subnet3->setT1Percent(0.50); @@ -710,7 +712,9 @@ TEST(CfgSubnets6Test, unparseSubnet) { " \"min-valid-lifetime\": 100,\n" " \"max-valid-lifetime\": 300,\n" " \"rapid-commit\": false,\n" + " \"reservations-global\": false,\n" " \"reservations-in-subnet\": true,\n" + " \"reservations-out-of-pool\": false,\n" " \"pools\": [ ],\n" " \"pd-pools\": [ ],\n" " \"option-data\": [ ],\n" @@ -1079,7 +1083,9 @@ TEST(CfgSubnets6Test, teeTimePercentValidation) { " \"valid-lifetime\": 300, \n" " \"client-class\": \"\", \n" " \"require-client-classes\": [] \n," - " \"reservations-in-subnet\": true\n" + " \"reservations-global\": false, \n" + " \"reservations-in-subnet\": true, \n" + " \"reservations-out-of-pool\": false \n" " }"; @@ -1142,7 +1148,9 @@ TEST(CfgSubnets6Test, preferredLifetimeValidation) { " \"valid-lifetime\": 300, \n" " \"client-class\": \"\", \n" " \"require-client-classes\": [] \n," - " \"reservations-in-subnet\": true\n" + " \"reservations-global\": false, \n" + " \"reservations-in-subnet\": true, \n" + " \"reservations-out-of-pool\": false \n" " }"; @@ -1377,7 +1385,9 @@ TEST(CfgSubnets6Test, hostnameSanitizierValidation) { " \"valid-lifetime\": 300, \n" " \"client-class\": \"\", \n" " \"require-client-classes\": [] \n," - " \"reservations-in-subnet\": true\n" + " \"reservations-global\": false, \n" + " \"reservations-in-subnet\": true, \n" + " \"reservations-out-of-pool\": false \n" " }"; data::ElementPtr elems; @@ -1447,7 +1457,9 @@ TEST(CfgSubnets6Test, cacheParamValidation) { " \"valid-lifetime\": 300, \n" " \"client-class\": \"\", \n" " \"require-client-classes\": [] \n," - " \"reservations-in-subnet\": true\n" + " \"reservations-global\": false, \n" + " \"reservations-in-subnet\": true, \n" + " \"reservations-out-of-pool\": false \n" " }"; data::ElementPtr elems; diff --git a/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc b/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc index d60b9951e0..c08742e2c8 100644 --- a/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc +++ b/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc @@ -2728,8 +2728,14 @@ TEST_F(ParseConfigTest, defaultSubnet4) { EXPECT_TRUE(subnet->getT2().unspecified()); EXPECT_EQ(0, subnet->getT2().get()); - EXPECT_TRUE(subnet->getHostReservationMode().unspecified()); - EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode().get()); + EXPECT_TRUE(subnet->getReservationsGlobal().unspecified()); + EXPECT_FALSE(subnet->getReservationsGlobal().get()); + + EXPECT_TRUE(subnet->getReservationsInSubnet().unspecified()); + EXPECT_TRUE(subnet->getReservationsInSubnet().get()); + + EXPECT_TRUE(subnet->getReservationsOutOfPool().unspecified()); + EXPECT_FALSE(subnet->getReservationsOutOfPool().get()); EXPECT_TRUE(subnet->getCalculateTeeTimes().unspecified()); EXPECT_FALSE(subnet->getCalculateTeeTimes().get()); @@ -2832,8 +2838,14 @@ TEST_F(ParseConfigTest, defaultSubnet6) { EXPECT_TRUE(subnet->getT2().unspecified()); EXPECT_EQ(0, subnet->getT2().get()); - EXPECT_TRUE(subnet->getHostReservationMode().unspecified()); - EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode().get()); + EXPECT_TRUE(subnet->getReservationsGlobal().unspecified()); + EXPECT_FALSE(subnet->getReservationsGlobal().get()); + + EXPECT_TRUE(subnet->getReservationsInSubnet().unspecified()); + EXPECT_TRUE(subnet->getReservationsInSubnet().get()); + + EXPECT_TRUE(subnet->getReservationsOutOfPool().unspecified()); + EXPECT_FALSE(subnet->getReservationsOutOfPool().get()); EXPECT_TRUE(subnet->getCalculateTeeTimes().unspecified()); EXPECT_FALSE(subnet->getCalculateTeeTimes().get()); @@ -2918,8 +2930,14 @@ TEST_F(ParseConfigTest, defaultSharedNetwork4) { EXPECT_TRUE(network->getT2().unspecified()); EXPECT_EQ(0, network->getT2().get()); - EXPECT_TRUE(network->getHostReservationMode().unspecified()); - EXPECT_EQ(Network::HR_ALL, network->getHostReservationMode().get()); + EXPECT_TRUE(network->getReservationsGlobal().unspecified()); + EXPECT_FALSE(network->getReservationsGlobal().get()); + + EXPECT_TRUE(network->getReservationsInSubnet().unspecified()); + EXPECT_TRUE(network->getReservationsInSubnet().get()); + + EXPECT_TRUE(network->getReservationsOutOfPool().unspecified()); + EXPECT_FALSE(network->getReservationsOutOfPool().get()); EXPECT_TRUE(network->getCalculateTeeTimes().unspecified()); EXPECT_FALSE(network->getCalculateTeeTimes().get()); @@ -2999,8 +3017,14 @@ TEST_F(ParseConfigTest, defaultSharedNetwork6) { EXPECT_TRUE(network->getT2().unspecified()); EXPECT_EQ(0, network->getT2().get()); - EXPECT_TRUE(network->getHostReservationMode().unspecified()); - EXPECT_EQ(Network::HR_ALL, network->getHostReservationMode().get()); + EXPECT_TRUE(network->getReservationsGlobal().unspecified()); + EXPECT_FALSE(network->getReservationsGlobal().get()); + + EXPECT_TRUE(network->getReservationsInSubnet().unspecified()); + EXPECT_TRUE(network->getReservationsInSubnet().get()); + + EXPECT_TRUE(network->getReservationsOutOfPool().unspecified()); + EXPECT_FALSE(network->getReservationsOutOfPool().get()); EXPECT_TRUE(network->getCalculateTeeTimes().unspecified()); EXPECT_FALSE(network->getCalculateTeeTimes().get()); diff --git a/src/lib/dhcpsrv/tests/network_unittest.cc b/src/lib/dhcpsrv/tests/network_unittest.cc index 7c88e21145..c9dc04b61f 100644 --- a/src/lib/dhcpsrv/tests/network_unittest.cc +++ b/src/lib/dhcpsrv/tests/network_unittest.cc @@ -145,17 +145,6 @@ public: ElementPtr globals_; }; -// This test verifies conversions of host reservation mode names to -// appropriate enum values. -TEST_F(NetworkTest, hrModeFromString) { - EXPECT_EQ(Network::HR_DISABLED, Network::hrModeFromString("off")); - EXPECT_EQ(Network::HR_DISABLED, Network::hrModeFromString("disabled")); - EXPECT_EQ(Network::HR_OUT_OF_POOL, Network::hrModeFromString("out-of-pool")); - EXPECT_EQ(Network::HR_GLOBAL, Network::hrModeFromString("global")); - EXPECT_EQ(Network::HR_ALL, Network::hrModeFromString("all")); - EXPECT_THROW(Network::hrModeFromString("bogus"), isc::BadValue); -} - // This test verifies that the inheritance is supported for certain // network parameters. TEST_F(NetworkTest, inheritanceSupport4) { @@ -163,7 +152,9 @@ TEST_F(NetworkTest, inheritanceSupport4) { globals_->set("valid-lifetime", Element::create(80)); globals_->set("renew-timer", Element::create(80)); globals_->set("rebind-timer", Element::create(80)); - globals_->set("reservation-mode", Element::create("disabled")); + globals_->set("reservations-global", Element::create(false)); + globals_->set("reservations-in-subnet", Element::create(false)); + globals_->set("reservations-out-of-pool", Element::create(false)); globals_->set("calculate-tee-times", Element::create(false)); globals_->set("t1-percent", Element::create(0.75)); globals_->set("t2-percent", Element::create(0.6)); @@ -185,9 +176,6 @@ TEST_F(NetworkTest, inheritanceSupport4) { globals_->set("cache-max-age", Element::create(20)); globals_->set("ddns-update-on-renew", Element::create(true)); globals_->set("ddns-use-conflict-resolution", Element::create(true)); - globals_->set("reservations-out-of-pool", Element::create(false)); - globals_->set("reservations-in-subnet", Element::create(false)); - globals_->set("reservations-global", Element::create(false)); // For each parameter for which inheritance is supported run // the test that checks if the values are inherited properly. @@ -214,18 +202,22 @@ TEST_F(NetworkTest, inheritanceSupport4) { 60, 80); } { - SCOPED_TRACE("reservation-mode"); - testNetworkInheritance(&Network::getHostReservationMode, - &Network::setHostReservationMode, - Network::HR_OUT_OF_POOL, - Network::HR_DISABLED); + SCOPED_TRACE("reservation-global"); + testNetworkInheritance(&Network::getReservationsGlobal, + &Network::setReservationsGlobal, + true, false); } { - SCOPED_TRACE("reservations-global"); - testNetworkInheritance(&Network::getHostReservationMode, - &Network::setHostReservationMode, - Network::HR_OUT_OF_POOL, - Network::HR_DISABLED); + SCOPED_TRACE("reservation-in-subnet"); + testNetworkInheritance(&Network::getReservationsInSubnet, + &Network::setReservationsInSubnet, + true, false); + } + { + SCOPED_TRACE("reservation-out-of-pool"); + testNetworkInheritance(&Network::getReservationsOutOfPool, + &Network::setReservationsOutOfPool, + true, false); } { SCOPED_TRACE("calculate-tee-times"); diff --git a/src/lib/dhcpsrv/tests/reservation_modes_parser_unittest.cc b/src/lib/dhcpsrv/tests/reservation_modes_parser_unittest.cc deleted file mode 100644 index a956480f67..0000000000 --- a/src/lib/dhcpsrv/tests/reservation_modes_parser_unittest.cc +++ /dev/null @@ -1,272 +0,0 @@ -// Copyright (C) 2018-2020 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 - -#include -#include -#include -#include -#include - -using namespace isc::data; -using namespace isc::dhcp; -using namespace isc::test; -using namespace isc::util; - -namespace { - -/// @brief Test fixture class for @c HostReservationModesParser -class HostReservationModesParserTest : public ::testing::Test { -protected: - - /// @brief Setup for each test. - /// - /// Clears the configuration in the @c CfgMgr. - virtual void SetUp(); - - /// @brief Cleans up after each test. - /// - /// Clears the configuration in the @c CfgMgr. - virtual void TearDown(); - -}; - -void -HostReservationModesParserTest::SetUp() { - CfgMgr::instance().clear(); -} - -void -HostReservationModesParserTest::TearDown() { - CfgMgr::instance().clear(); -} - -// Verifies that HostReservationModesParser handles -// expected valid reservation-modes content -TEST_F(HostReservationModesParserTest, validContent) { - struct Scenario { - std::string description_; - std::string json_; - uint8_t expected_result_; - }; - - std::vector scenarios = { - { - "reservation modes disabled specifying all parameters", - "{ \n" - " \"reservations-global\": false, \n" - " \"reservations-in-subnet\": false, \n" - " \"reservations-out-of-pool\": false \n" - "} \n", - static_cast(Network::HR_DISABLED) - }, - { - "reservation modes disabled specifying only global", - "{ \n" - " \"reservations-global\": false \n" - "} \n", - static_cast(Network::HR_DISABLED) - }, - { - "reservation modes disabled specifying only in-subnet", - "{ \n" - " \"reservations-in-subnet\": false \n" - "} \n", - static_cast(Network::HR_DISABLED) - }, - { - "reservation modes disabled specifying only out-of-pool", - "{ \n" - " \"reservations-out-of-pool\": false \n" - "} \n", - static_cast(Network::HR_DISABLED) - }, - { - "reservation modes global enabled specifying all parameters", - "{ \n" - " \"reservations-global\": true, \n" - " \"reservations-in-subnet\": false, \n" - " \"reservations-out-of-pool\": false \n" - "} \n", - static_cast(Network::HR_GLOBAL) - }, - { - "reservation modes global enabled specifying only global", - "{ \n" - " \"reservations-global\": true \n" - "} \n", - static_cast(Network::HR_GLOBAL) - }, - { - "reservation modes in-subnet enabled specifying all parameters", - "{ \n" - " \"reservations-global\": false, \n" - " \"reservations-in-subnet\": true, \n" - " \"reservations-out-of-pool\": false \n" - "} \n", - static_cast(Network::HR_IN_SUBNET) - }, - { - "reservation modes in-subnet enabled specifying only in-subnet", - "{ \n" - " \"reservations-in-subnet\": true \n" - "} \n", - static_cast(Network::HR_IN_SUBNET) - }, - { - "reservation modes global and in-subnet enabled specifying all parameters", - "{ \n" - " \"reservations-global\": true, \n" - " \"reservations-in-subnet\": true, \n" - " \"reservations-out-of-pool\": false \n" - "} \n", - static_cast(Network::HR_GLOBAL|Network::HR_IN_SUBNET) - }, - { - "reservation modes global and in-subnet enabled specifying global and in-subnet", - "{ \n" - " \"reservations-global\": true, \n" - " \"reservations-in-subnet\": true \n" - "} \n", - static_cast(Network::HR_GLOBAL|Network::HR_IN_SUBNET) - }, - { - "reservation modes out-of-pool enabled specifying all parameters", - "{ \n" - " \"reservations-global\": false, \n" - " \"reservations-in-subnet\": true, \n" - " \"reservations-out-of-pool\": true \n" - "} \n", - static_cast(Network::HR_OUT_OF_POOL) - }, - { - "reservation modes out-of-pool enabled specifying in-subnet and out-of-pool", - "{ \n" - " \"reservations-in-subnet\": true, \n" - " \"reservations-out-of-pool\": true \n" - "} \n", - static_cast(Network::HR_OUT_OF_POOL) - }, - { - "reservation modes out-of-pool enabled specifying only out-of-pool", - "{ \n" - " \"reservations-out-of-pool\": true \n" - "} \n", - static_cast(Network::HR_OUT_OF_POOL) - }, - { - "reservation modes global and out-of-pool enabled specifying all parameters", - "{ \n" - " \"reservations-global\": true, \n" - " \"reservations-in-subnet\": true, \n" - " \"reservations-out-of-pool\": true \n" - "} \n", - static_cast(Network::HR_OUT_OF_POOL|Network::HR_GLOBAL) - }, - { - "reservation modes global and out-of-pool enabled specifying global and out-of-pool", - "{ \n" - " \"reservations-global\": true, \n" - " \"reservations-out-of-pool\": true \n" - "} \n", - static_cast(Network::HR_OUT_OF_POOL|Network::HR_GLOBAL) - } - }; - - // Iterate over the valid scenarios and verify they succeed. - ConstElementPtr config_elems; - Network::HRMode reservation_modes; - for (auto scenario : scenarios) { - SCOPED_TRACE(scenario.description_); - { - // Construct the config JSON - ASSERT_NO_THROW(config_elems = Element::fromJSON(scenario.json_)) - << "invalid JSON, test is broken"; - - // Parsing config into a reservation modes parser should succeed. - HostReservationModesParser parser; - try { - reservation_modes = parser.parse(config_elems); - } catch (const std::exception& ex) { - ADD_FAILURE() << "parser threw an exception: " << ex.what(); - } - - // Verify the resultant reservation-modes. - ASSERT_EQ(scenario.expected_result_, reservation_modes); - } - } -} - -// Verifies that HostReservationModesParser correctly catches -// invalid reservation-modes content -TEST_F(HostReservationModesParserTest, invalidContent) { - struct Scenario { - std::string description_; - std::string json_; - }; - - std::vector scenarios = { - { - "global not boolean", - "{ \n" - " \"reservations-global\": \"always\" \n" - "} \n" - }, - { - "in-subnet not boolean", - "{ \n" - " \"reservations-in-subnet\": \"always\" \n" - "} \n" - }, - { - "out-of-pool not boolean", - "{ \n" - " \"reservations-out-of-pool\": \"always\" \n" - "} \n" - }, - { - "reservation modes out-of-pool enabled specifying all parameters", - "{ \n" - " \"reservations-global\": false, \n" - " \"reservations-in-subnet\": false, \n" - " \"reservations-out-of-pool\": true \n" - "} \n" - }, - { - "reservation modes out-of-pool enabled specifying all parameters", - "{ \n" - " \"reservations-global\": true, \n" - " \"reservations-in-subnet\": false, \n" - " \"reservations-out-of-pool\": true \n" - "} \n" - }, - { - "reservation modes out-of-pool enabled specifying in-subnet and out-of-pool", - "{ \n" - " \"reservations-in-subnet\": false, \n" - " \"reservations-out-of-pool\": true \n" - "} \n" - }, - }; - - // Iterate over the invalid scenarios and verify they throw exception. - ConstElementPtr config_elems; - for (auto scenario : scenarios) { - SCOPED_TRACE(scenario.description_); - { - // Construct the config JSON - ASSERT_NO_THROW(config_elems = Element::fromJSON(scenario.json_)) - << "invalid JSON, test is broken"; - - // Parsing config into a reservation modes parser should succeed. - HostReservationModesParser parser; - EXPECT_THROW(parser.parse(config_elems), DhcpConfigError); - } - } -} - -}; // anonymous namespace diff --git a/src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc b/src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc index ae3c2f66f8..b91ea2b34c 100644 --- a/src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc +++ b/src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc @@ -128,6 +128,8 @@ public: " \"rebind-timer\": 199," " \"relay\": { \"ip-addresses\": [ \"10.1.1.1\" ] }," " \"renew-timer\": 99," + " \"reservations-global\": false," + " \"reservations-in-subnet\": true," " \"reservations-out-of-pool\": true," " \"server-hostname\": \"example.org\"," " \"require-client-classes\": [ \"runner\" ]," @@ -173,7 +175,9 @@ public: " \"boot-file-name\": \"\"," " \"client-class\": \"\"," " \"require-client-classes\": []\n," + " \"reservations-global\": false," " \"reservations-in-subnet\": true," + " \"reservations-out-of-pool\": false," " \"4o6-interface\": \"\"," " \"4o6-interface-id\": \"\"," " \"4o6-subnet\": \"\"," @@ -198,7 +202,9 @@ public: " \"boot-file-name\": \"\"," " \"client-class\": \"\"," " \"require-client-classes\": []\n," + " \"reservations-global\": false," " \"reservations-in-subnet\": true," + " \"reservations-out-of-pool\": false," " \"4o6-interface\": \"\"," " \"4o6-interface-id\": \"\"," " \"4o6-subnet\": \"\"," @@ -259,7 +265,9 @@ TEST_F(SharedNetwork4ParserTest, parse) { EXPECT_EQ("/dev/null", network->getFilename().get()); EXPECT_EQ("10.0.0.1", network->getSiaddr().get().toText()); EXPECT_EQ("example.org", network->getSname().get()); - EXPECT_EQ(Network::HR_OUT_OF_POOL, network->getHostReservationMode()); + EXPECT_FALSE(network->getReservationsGlobal()); + EXPECT_TRUE(network->getReservationsInSubnet()); + EXPECT_TRUE(network->getReservationsOutOfPool()); EXPECT_TRUE(network->getDdnsSendUpdates().get()); EXPECT_TRUE(network->getDdnsOverrideNoUpdate().get()); EXPECT_TRUE(network->getDdnsOverrideClientUpdate().get()); @@ -547,6 +555,8 @@ public: " \"relay\": { \"ip-addresses\": [ \"2001:db8:1::1\" ] }," " \"renew-timer\": 99," " \"require-client-classes\": [ \"runner\" ]," + " \"reservations-global\": false," + " \"reservations-in-subnet\": true," " \"reservations-out-of-pool\": true," " \"user-context\": { }," " \"valid-lifetime\": 399," @@ -589,7 +599,9 @@ public: " \"max-valid-lifetime\": 500," " \"client-class\": \"\"," " \"require-client-classes\": []\n," + " \"reservations-global\": false," " \"reservations-in-subnet\": true," + " \"reservations-out-of-pool\": false," " \"rapid-commit\": false," " \"hostname-char-set\": \"\"" " }," @@ -604,7 +616,9 @@ public: " \"valid-lifetime\": 40," " \"client-class\": \"\"," " \"require-client-classes\": []\n," + " \"reservations-global\": false," " \"reservations-in-subnet\": true," + " \"reservations-out-of-pool\": false," " \"rapid-commit\": false" " }" " ]" diff --git a/src/lib/dhcpsrv/tests/shared_network_unittest.cc b/src/lib/dhcpsrv/tests/shared_network_unittest.cc index c7b09e0769..4976b9659a 100644 --- a/src/lib/dhcpsrv/tests/shared_network_unittest.cc +++ b/src/lib/dhcpsrv/tests/shared_network_unittest.cc @@ -18,6 +18,7 @@ #include #include #include + using namespace isc; using namespace isc::asiolink; using namespace isc::dhcp; @@ -52,8 +53,14 @@ TEST(SharedNetwork4Test, defaults) { EXPECT_TRUE(network->getT2().unspecified()); EXPECT_EQ(0, network->getT2().get()); - EXPECT_TRUE(network->getHostReservationMode().unspecified()); - EXPECT_EQ(Network::HR_ALL, network->getHostReservationMode().get()); + EXPECT_TRUE(network->getReservationsGlobal().unspecified()); + EXPECT_FALSE(network->getReservationsGlobal().get()); + + EXPECT_TRUE(network->getReservationsInSubnet().unspecified()); + EXPECT_TRUE(network->getReservationsInSubnet().get()); + + EXPECT_TRUE(network->getReservationsOutOfPool().unspecified()); + EXPECT_FALSE(network->getReservationsOutOfPool().get()); EXPECT_TRUE(network->getCalculateTeeTimes().unspecified()); EXPECT_FALSE(network->getCalculateTeeTimes().get()); @@ -614,7 +621,9 @@ TEST(SharedNetwork4Test, unparse) { network->addRelayAddress(IOAddress("192.168.2.1")); network->setAuthoritative(false); network->setMatchClientId(false); - network->setHostReservationMode(Network::HR_ALL); + network->setReservationsGlobal(false); + network->setReservationsInSubnet(true); + network->setReservationsOutOfPool(false); // Add several subnets. Subnet4Ptr subnet1(new Subnet4(IOAddress("10.0.0.0"), 8, 10, 20, 30, @@ -639,7 +648,9 @@ TEST(SharedNetwork4Test, unparse) { " },\n" " \"renew-timer\": 100,\n" " \"require-client-classes\": [ \"foo\" ],\n" + " \"reservations-global\": false,\n" " \"reservations-in-subnet\": true,\n" + " \"reservations-out-of-pool\": false,\n" " \"subnet4\": [\n" " {\n" " \"4o6-interface\": \"\",\n" @@ -753,8 +764,14 @@ TEST(SharedNetwork6Test, defaults) { EXPECT_TRUE(network->getT2().unspecified()); EXPECT_EQ(0, network->getT2().get()); - EXPECT_TRUE(network->getHostReservationMode().unspecified()); - EXPECT_EQ(Network::HR_ALL, network->getHostReservationMode().get()); + EXPECT_TRUE(network->getReservationsGlobal().unspecified()); + EXPECT_FALSE(network->getReservationsGlobal().get()); + + EXPECT_TRUE(network->getReservationsInSubnet().unspecified()); + EXPECT_TRUE(network->getReservationsInSubnet().get()); + + EXPECT_TRUE(network->getReservationsOutOfPool().unspecified()); + EXPECT_FALSE(network->getReservationsOutOfPool().get()); EXPECT_TRUE(network->getCalculateTeeTimes().unspecified()); EXPECT_FALSE(network->getCalculateTeeTimes().get()); @@ -1306,7 +1323,9 @@ TEST(SharedNetwork6Test, unparse) { network->addRelayAddress(IOAddress("2001:db8:1::8")); network->setRapidCommit(true); - network->setHostReservationMode(Network::HR_ALL); + network->setReservationsGlobal(false); + network->setReservationsInSubnet(true); + network->setReservationsOutOfPool(false); // Add several subnets. Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 64, 10, 20, 30, @@ -1330,7 +1349,9 @@ TEST(SharedNetwork6Test, unparse) { " },\n" " \"renew-timer\": 100,\n" " \"require-client-classes\": [ \"foo\" ],\n" + " \"reservations-global\": false,\n" " \"reservations-in-subnet\": true,\n" + " \"reservations-out-of-pool\": false,\n" " \"subnet6\": [\n" " {\n" " \"id\": 1,\n" diff --git a/src/lib/dhcpsrv/tests/subnet_unittest.cc b/src/lib/dhcpsrv/tests/subnet_unittest.cc index c673242b64..461edb80af 100644 --- a/src/lib/dhcpsrv/tests/subnet_unittest.cc +++ b/src/lib/dhcpsrv/tests/subnet_unittest.cc @@ -83,8 +83,14 @@ TEST(Subnet4Test, defaults) { EXPECT_TRUE(subnet.getT2().unspecified()); EXPECT_EQ(0, subnet.getT2().get()); - EXPECT_TRUE(subnet.getHostReservationMode().unspecified()); - EXPECT_EQ(Network::HR_ALL, subnet.getHostReservationMode().get()); + EXPECT_TRUE(subnet.getReservationsGlobal().unspecified()); + EXPECT_FALSE(subnet.getReservationsGlobal().get()); + + EXPECT_TRUE(subnet.getReservationsInSubnet().unspecified()); + EXPECT_TRUE(subnet.getReservationsInSubnet().get()); + + EXPECT_TRUE(subnet.getReservationsOutOfPool().unspecified()); + EXPECT_FALSE(subnet.getReservationsOutOfPool().get()); EXPECT_TRUE(subnet.getCalculateTeeTimes().unspecified()); EXPECT_FALSE(subnet.getCalculateTeeTimes().get()); @@ -853,8 +859,14 @@ TEST(SharedNetwork6Test, defaults) { EXPECT_TRUE(subnet.getT2().unspecified()); EXPECT_EQ(0, subnet.getT2().get()); - EXPECT_TRUE(subnet.getHostReservationMode().unspecified()); - EXPECT_EQ(Network::HR_ALL, subnet.getHostReservationMode().get()); + EXPECT_TRUE(subnet.getReservationsGlobal().unspecified()); + EXPECT_FALSE(subnet.getReservationsGlobal().get()); + + EXPECT_TRUE(subnet.getReservationsInSubnet().unspecified()); + EXPECT_TRUE(subnet.getReservationsInSubnet().get()); + + EXPECT_TRUE(subnet.getReservationsOutOfPool().unspecified()); + EXPECT_FALSE(subnet.getReservationsOutOfPool().get()); EXPECT_TRUE(subnet.getCalculateTeeTimes().unspecified()); EXPECT_FALSE(subnet.getCalculateTeeTimes().get()); diff --git a/src/share/database/scripts/mysql/dhcpdb_create.mysql b/src/share/database/scripts/mysql/dhcpdb_create.mysql index a9f0766139..0718370810 100644 --- a/src/share/database/scripts/mysql/dhcpdb_create.mysql +++ b/src/share/database/scripts/mysql/dhcpdb_create.mysql @@ -3027,31 +3027,32 @@ SET version = '9', minor = '4'; # This line concludes database upgrade to version 9.4. -# Update reservation_mode value after separating flags. +# Add new reservations flags. +ALTER TABLE dhcp4_subnet + ADD COLUMN reservations_global BOOL DEFAULT NULL, + ADD COLUMN reservations_in_subnet BOOL DEFAULT NULL, + ADD COLUMN reservations_out_of_pool BOOL DEFAULT NULL; -# update old global to new value -UPDATE dhcp4_subnet SET reservation_mode = 4 WHERE reservation_mode = 2; -UPDATE dhcp4_shared_network SET reservation_mode = 4 WHERE reservation_mode = 2; +ALTER TABLE dhcp4_shared_network + ADD COLUMN reservations_global BOOL DEFAULT NULL, + ADD COLUMN reservations_in_subnet BOOL DEFAULT NULL, + ADD COLUMN reservations_out_of_pool BOOL DEFAULT NULL; -# update old all to new value -UPDATE dhcp4_subnet SET reservation_mode = 2 WHERE reservation_mode = 3; -UPDATE dhcp4_shared_network SET reservation_mode = 2 WHERE reservation_mode = 3; +ALTER TABLE dhcp6_subnet + ADD COLUMN reservations_global BOOL DEFAULT NULL, + ADD COLUMN reservations_in_subnet BOOL DEFAULT NULL, + ADD COLUMN reservations_out_of_pool BOOL DEFAULT NULL; -# update out-of-pool all to new value -UPDATE dhcp4_subnet SET reservation_mode = 3 WHERE reservation_mode = 1; -UPDATE dhcp4_shared_network SET reservation_mode = 3 WHERE reservation_mode = 1; +ALTER TABLE dhcp6_shared_network + ADD COLUMN reservations_global BOOL DEFAULT NULL, + ADD COLUMN reservations_in_subnet BOOL DEFAULT NULL, + ADD COLUMN reservations_out_of_pool BOOL DEFAULT NULL; -# update old global to new value -UPDATE dhcp6_subnet SET reservation_mode = 4 WHERE reservation_mode = 2; -UPDATE dhcp6_shared_network SET reservation_mode = 4 WHERE reservation_mode = 2; - -# update old all to new value -UPDATE dhcp6_subnet SET reservation_mode = 2 WHERE reservation_mode = 3; -UPDATE dhcp6_shared_network SET reservation_mode = 2 WHERE reservation_mode = 3; - -# update out-of-pool all to new value -UPDATE dhcp6_subnet SET reservation_mode = 3 WHERE reservation_mode = 1; -UPDATE dhcp6_shared_network SET reservation_mode = 3 WHERE reservation_mode = 1; +# DROP reservation_mode +ALTER TABLE dhcp4_subnet DROP COLUMN reservation_mode; +ALTER TABLE dhcp4_shared_network DROP COLUMN reservation_mode; +ALTER TABLE dhcp6_subnet DROP COLUMN reservation_mode; +ALTER TABLE dhcp6_shared_network DROP COLUMN reservation_mode; # Update the schema version number UPDATE schema_version diff --git a/src/share/database/scripts/mysql/upgrade_9.4_to_9.5.sh.in b/src/share/database/scripts/mysql/upgrade_9.4_to_9.5.sh.in index 13297d2eff..da58d017ca 100644 --- a/src/share/database/scripts/mysql/upgrade_9.4_to_9.5.sh.in +++ b/src/share/database/scripts/mysql/upgrade_9.4_to_9.5.sh.in @@ -18,34 +18,136 @@ fi mysql "$@" <