diff --git a/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp6.cc b/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp6.cc deleted file mode 100644 index f354932d36..0000000000 --- a/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp6.cc +++ /dev/null @@ -1,2069 +0,0 @@ -// Copyright (C) 2021 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -using namespace isc::cb; -using namespace isc::db; -using namespace isc::data; -using namespace isc::asiolink; -using namespace isc::log; -using namespace isc::util; - -namespace isc { -namespace dhcp { - -/// @brief Implementation of the Postgres Configuration Backend. -class PgSqlConfigBackendDHCPv6Impl : public PgSqlConfigBackendImpl { -public: - /// @brief Statement tags. - /// - /// The contents of the enum are indexes into the list of SQL statements. - /// It is assumed that the order is such that the indices of statements - /// reading the database are less than those of statements modifying the - /// database. - enum StatementIndex { - CREATE_AUDIT_REVISION, - GET_GLOBAL_PARAMETER6, - GET_ALL_GLOBAL_PARAMETERS6, - GET_MODIFIED_GLOBAL_PARAMETERS6, - GET_SUBNET6_ID_NO_TAG, - GET_SUBNET6_ID_ANY, - GET_SUBNET6_ID_UNASSIGNED, - GET_SUBNET6_PREFIX_NO_TAG, - GET_SUBNET6_PREFIX_ANY, - GET_SUBNET6_PREFIX_UNASSIGNED, - GET_ALL_SUBNETS6, - GET_ALL_SUBNETS6_UNASSIGNED, - GET_MODIFIED_SUBNETS6, - GET_MODIFIED_SUBNETS6_UNASSIGNED, - GET_SHARED_NETWORK_SUBNETS6, - GET_POOL6_RANGE, - GET_POOL6_RANGE_ANY, - GET_PD_POOL, - GET_PD_POOL_ANY, - GET_SHARED_NETWORK6_NAME_NO_TAG, - GET_SHARED_NETWORK6_NAME_ANY, - GET_SHARED_NETWORK6_NAME_UNASSIGNED, - GET_ALL_SHARED_NETWORKS6, - GET_ALL_SHARED_NETWORKS6_UNASSIGNED, - GET_MODIFIED_SHARED_NETWORKS6, - GET_MODIFIED_SHARED_NETWORKS6_UNASSIGNED, - GET_OPTION_DEF6_CODE_SPACE, - GET_ALL_OPTION_DEFS6, - GET_MODIFIED_OPTION_DEFS6, - GET_OPTION6_CODE_SPACE, - GET_ALL_OPTIONS6, - GET_MODIFIED_OPTIONS6, - GET_OPTION6_SUBNET_ID_CODE_SPACE, - GET_OPTION6_POOL_ID_CODE_SPACE, - GET_OPTION6_PD_POOL_ID_CODE_SPACE, - GET_OPTION6_SHARED_NETWORK_CODE_SPACE, - GET_AUDIT_ENTRIES6_TIME, - GET_SERVER6, - GET_ALL_SERVERS6, - INSERT_GLOBAL_PARAMETER6, - INSERT_GLOBAL_PARAMETER6_SERVER, - INSERT_SUBNET6, - INSERT_SUBNET6_SERVER, - INSERT_POOL6, - INSERT_PD_POOL, - INSERT_SHARED_NETWORK6, - INSERT_SHARED_NETWORK6_SERVER, - INSERT_OPTION_DEF6, - INSERT_OPTION_DEF6_SERVER, - INSERT_OPTION6, - INSERT_OPTION6_SERVER, - INSERT_SERVER6, - UPDATE_GLOBAL_PARAMETER6, - UPDATE_SUBNET6, - UPDATE_SHARED_NETWORK6, - UPDATE_OPTION_DEF6, - UPDATE_OPTION6, - UPDATE_OPTION6_SUBNET_ID, - UPDATE_OPTION6_POOL_ID, - UPDATE_OPTION6_PD_POOL_ID, - UPDATE_OPTION6_SHARED_NETWORK, - UPDATE_SERVER6, - DELETE_GLOBAL_PARAMETER6, - DELETE_ALL_GLOBAL_PARAMETERS6, - DELETE_ALL_GLOBAL_PARAMETERS6_UNASSIGNED, - DELETE_SUBNET6_ID_WITH_TAG, - DELETE_SUBNET6_ID_ANY, - DELETE_SUBNET6_PREFIX_WITH_TAG, - DELETE_SUBNET6_PREFIX_ANY, - DELETE_ALL_SUBNETS6, - DELETE_ALL_SUBNETS6_UNASSIGNED, - DELETE_ALL_SUBNETS6_SHARED_NETWORK_NAME, - DELETE_SUBNET6_SERVER, - DELETE_POOLS6, - DELETE_PD_POOLS, - DELETE_SHARED_NETWORK6_NAME_WITH_TAG, - DELETE_SHARED_NETWORK6_NAME_ANY, - DELETE_ALL_SHARED_NETWORKS6, - DELETE_ALL_SHARED_NETWORKS6_UNASSIGNED, - DELETE_SHARED_NETWORK6_SERVER, - DELETE_OPTION_DEF6_CODE_NAME, - DELETE_ALL_OPTION_DEFS6, - DELETE_ALL_OPTION_DEFS6_UNASSIGNED, - DELETE_OPTION6, - DELETE_ALL_GLOBAL_OPTIONS6_UNASSIGNED, - DELETE_OPTION6_SUBNET_ID, - DELETE_OPTION6_POOL_RANGE, - DELETE_OPTION6_PD_POOL, - DELETE_OPTION6_SHARED_NETWORK, - DELETE_OPTIONS6_SUBNET_ID_PREFIX, - DELETE_OPTIONS6_SHARED_NETWORK, - DELETE_SERVER6, - DELETE_ALL_SERVERS6, - NUM_STATEMENTS - }; - - /// @brief Constructor. - /// - /// @param parameters A data structure relating keywords and values - /// concerned with the database. - explicit PgSqlConfigBackendDHCPv6Impl(const DatabaseConnection::ParameterMap& parameters); - - /// @brief Destructor. - ~PgSqlConfigBackendDHCPv6Impl(); - - /// @brief Sends query to retrieve global parameter. - /// - /// @param server_selector Server selector. - /// @param name Name of the parameter to be retrieved. - /// - /// @return Pointer to the retrieved value or null if such parameter - /// doesn't exist. - StampedValuePtr - getGlobalParameter6(const ServerSelector& server_selector, const std::string& name) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Sends query to insert or update global parameter. - /// - /// @param server_selector Server selector. - /// @param name Name of the global parameter. - /// @param value Value of the global parameter. - void createUpdateGlobalParameter6(const db::ServerSelector& server_selector, - const StampedValuePtr& value) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Sends query to retrieve single subnet by id. - /// - /// @param server_selector Server selector. - /// @param subnet_id Subnet identifier. - /// - /// @return Pointer to the returned subnet or NULL if such subnet - /// doesn't exist. - Subnet6Ptr getSubnet6(const ServerSelector& server_selector, const SubnetID& subnet_id) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Sends query to retrieve single subnet by prefix. - /// - /// The prefix should be in the following format: "2001:db8:1::/64". - /// - /// @param server_selector Server selector. - /// @param subnet_id Subnet identifier. - /// - /// @return Pointer to the returned subnet or NULL if such subnet - /// doesn't exist. - Subnet6Ptr getSubnet6(const ServerSelector& server_selector, const std::string& subnet_prefix) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Sends query to retrieve all subnets. - /// - /// @param server_selector Server selector. - /// @param [out] subnets Reference to the subnet collection structure where - /// subnets should be inserted. - void getAllSubnets6(const ServerSelector& server_selector, Subnet6Collection& subnets) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Sends query to retrieve modified subnets. - /// - /// @param server_selector Server selector. - /// @param modification_ts Lower bound modification timestamp. - /// @param [out] subnets Reference to the subnet collection structure where - /// subnets should be inserted. - void getModifiedSubnets6(const ServerSelector& server_selector, - const boost::posix_time::ptime& modification_ts, - Subnet6Collection& subnets) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Sends query to retrieve all subnets belonging to a shared network. - /// - /// @param server_selector Server selector. - /// @param shared_network_name Name of the shared network for which the - /// subnets should be retrieved. - /// @param [out] subnets Reference to the subnet collection structure where - /// subnets should be inserted. - void getSharedNetworkSubnets6(const ServerSelector& server_selector, - const std::string& shared_network_name, - Subnet6Collection& subnets) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Sends query to retrieve multiple pools. - /// - /// Query should order pools by id. - /// - /// @param index Index of the query to be used. - /// @param in_bindings Input bindings specifying selection criteria. The - /// size of the bindings collection must match the number of placeholders - /// in the prepared statement. The input bindings collection must be empty - /// if the query contains no WHERE clause. - /// @param [out] pools Reference to the container where fetched pools - /// will be inserted. - /// @param [out] pool_ids Identifiers of the pools returned in @c pools - /// argument. - /// @todo: add void getPools(const StatementIndex& index, const MySqlBindingCollection& - /// in_bindings, PoolCollection& pools, std::vector& pool_ids) { - - /// @brief Sends query to retrieve multiple pd pools. - /// - /// Query should order pd pools by id. - /// - /// @param index Index of the query to be used. - /// @param in_bindings Input bindings specifying selection criteria. The - /// size of the bindings collection must match the number of placeholders - /// in the prepared statement. The input bindings collection must be empty - /// if the query contains no WHERE clause. - /// @param [out] pd_pools Reference to the container where fetched pools - /// will be inserted. - /// @param [out] pd_pool_ids Identifiers of the pd pools returned in - /// @c pd_pools argument. - /// @todo add: void getPdPools(const StatementIndex& index, const MySqlBindingCollection& - /// in_bindings, - /// PoolCollection& pd_pools, std::vector& pd_pool_ids) { - - /// @brief Sends query to retrieve single pool by address range. - /// - /// @param server_selector Server selector. - /// @param pool_start_address Lower bound pool address. - /// @param pool_end_address Upper bound pool address. - /// @param pool_id Pool identifier for the returned pool. - /// @return Pointer to the pool or null if no such pool found. - Pool6Ptr getPool6(const ServerSelector& server_selector, - const IOAddress& pool_start_address, - const IOAddress& pool_end_address, - uint64_t& pool_id) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Sends query to retrieve single pd pool. - /// - /// @param server_selector Server selector. - /// @param pd_pool_prefix Address part of the pd pool prefix. - /// @param pd_pool_prefix_length Length of the pd pool prefix. - /// @param pd_pool_id Pool identifier for the returned pool. - /// @return Pointer to the pool or null if no such pool found. - Pool6Ptr getPdPool6(const ServerSelector& server_selector, - const asiolink::IOAddress& pd_pool_prefix, - const uint8_t pd_pool_prefix_length, - uint64_t& pd_pool_id) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Sends query to insert or update subnet. - /// - /// @param server_selector Server selector. - /// @param subnet Pointer to the subnet to be inserted or updated. - void createUpdateSubnet6(const ServerSelector& server_selector, const Subnet6Ptr& subnet) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Inserts new IPv6 pool to the database. - /// - /// @param server_selector Server selector. - /// @param pool Pointer to the pool to be inserted. - /// @param subnet Pointer to the subnet that this pool belongs to. - void createPool6(const ServerSelector& server_selector, - const Pool6Ptr& pool, - const Subnet6Ptr& subnet) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Inserts new IPv6 pd pool to the database. - /// - /// @param server_selector Server selector. - /// @param pd_pool Pointer to the pd pool to be inserted. - /// @param subnet Pointer to the subnet that this pd pool belongs to. - void createPdPool6(const ServerSelector& server_selector, - const Pool6Ptr& pd_pool, - const Subnet6Ptr& subnet) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Sends a query to delete data from a table. - /// - /// If creates a new audit revision for this change if such audit - /// revision doesn't exist yet (using ScopedAuditRevision mechanism). - /// - /// @tparam Args type of the arguments to be passed to one of the existing - /// @c deleteFromTable methods. - /// @param server_selector server selector. - /// @param operation operation which results in calling this function. This is - /// used for logging purposes. - /// @param log_message log message to be associated with the audit revision. - /// @param cascade_delete boolean flag indicating if we're performing - /// cascade delete. If set to true, the audit entries for the child - /// objects (e.g. DHCPoptions) won't be created. - /// @param keys arguments to be passed to one of the existing - /// @c deleteFromTable methods. - /// - /// @return Number of deleted entries. - template - uint64_t deleteTransactional(const int index, - const db::ServerSelector& server_selector, - const std::string& operation, - const std::string& log_message, - const bool cascade_delete, - Args&&... keys) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Sends query to delete subnet by id. - /// - /// @param server_selector Server selector. - /// @param subnet_id Identifier of the subnet to be deleted. - /// @return Number of deleted subnets. - uint64_t deleteSubnet6(const ServerSelector& server_selector, const SubnetID& subnet_id) { - int index = (server_selector.amAny() ? - PgSqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_ID_ANY : - PgSqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_ID_WITH_TAG); - return (deleteTransactional(index, server_selector, "deleting a subnet", "subnet deleted", - true, static_cast(subnet_id))); - } - - /// @brief Sends query to delete subnet by id. - /// - /// @param server_selector Server selector. - /// @param subnet_prefix Prefix of the subnet to be deleted. - /// @return Number of deleted subnets. - uint64_t - deleteSubnet6(const ServerSelector& server_selector, const std::string& subnet_prefix) { - int index = (server_selector.amAny() ? - PgSqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_PREFIX_ANY : - PgSqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_PREFIX_WITH_TAG); - return (deleteTransactional(index, server_selector, "deleting a subnet", "subnet deleted", - true, subnet_prefix)); - } - - /// @brief Deletes pools belonging to a subnet from the database. - /// - /// The query deletes all pools associated with the subnet's - /// identifier or prefix. - /// @param subnet Pointer to the subnet for which pools should be - /// deleted. - uint64_t deletePools6(const Subnet6Ptr& subnet) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Deletes prefix delegation pools belonging to a subnet from - /// the database. - /// - /// The query deletes all pd pools associated with the subnet's - /// identifier or prefix. - /// @param subnet Pointer to the subnet for which pd pools should be - /// deleted. - uint64_t deletePdPools6(const Subnet6Ptr& subnet) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Sends query to the database to retrieve multiple shared - /// networks. - /// - /// Query should order shared networks by id. - /// - /// @param index Index of the query to be used. - /// @param server_selector Server selector. - /// @param in_bindings Input bindings specifying selection criteria. The - /// size of the bindings collection must match the number of placeholders - /// in the prepared statement. The input bindings collection must be empty - /// if the query contains no WHERE clause. - /// @param [out] shared_networks Reference to the container where fetched - /// shared networks will be inserted. - /// @todo: implement void getSharedNetworks6(const StatementIndex& index, - /// const ServerSelector& server_selector, - /// const MySqlBindingCollection& in_bindings, - /// SharedNetwork6Collection& shared_networks) { - - /// @brief Sends query to retrieve single shared network by name. - /// - /// @param server_selector Server selector. - /// @param name Shared network name. - /// - /// @return Pointer to the returned shared network or NULL if such shared - /// network doesn't exist. - SharedNetwork6Ptr - getSharedNetwork6(const ServerSelector& server_selector, const std::string& name) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Sends query to retrieve all shared networks. - /// - /// @param server_selector Server selector. - /// @param [out] shared_networks Reference to the shared networks collection - /// structure where shared networks should be inserted. - void getAllSharedNetworks6(const ServerSelector& server_selector, - SharedNetwork6Collection& shared_networks) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Sends query to retrieve modified shared networks. - /// - /// @param server_selector Server selector. - /// @param modification_ts Lower bound modification timestamp. - /// @param [out] shared_networks Reference to the shared networks collection - /// structure where shared networks should be inserted. - void getModifiedSharedNetworks6(const ServerSelector& server_selector, - const boost::posix_time::ptime& modification_ts, - SharedNetwork6Collection& shared_networks) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Sends query to insert or update shared network. - /// - /// @param server_selector Server selector. - /// @param subnet Pointer to the shared network to be inserted or updated. - void createUpdateSharedNetwork6(const ServerSelector& server_selector, - const SharedNetwork6Ptr& shared_network) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Sends query to insert DHCP option. - /// - /// This method expects that the server selector contains exactly one - /// server tag. - /// - /// @param server_selector Server selector. - /// @param in_bindings Collection of bindings representing an option. - /// @todo: implement void insertOption6(const ServerSelector& server_selector, - /// const MySqlBindingCollection& in_bindings) { - - /// @brief Sends query to insert or update global DHCP option. - /// - /// @param server_selector Server selector. - /// @param option Pointer to the option descriptor encapsulating the option. - void - createUpdateOption6(const ServerSelector& server_selector, const OptionDescriptorPtr& option) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Sends query to insert or update DHCP option in a subnet. - /// - /// @param server_selector Server selector. - /// @param subnet_id Identifier of the subnet the option belongs to. - /// @param option Pointer to the option descriptor encapsulating the option. - /// @param cascade_update Boolean value indicating whether the update is - /// performed as part of the owning element, e.g. subnet. - void createUpdateOption6(const ServerSelector& server_selector, - const SubnetID& subnet_id, - const OptionDescriptorPtr& option, - const bool cascade_update) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Sends query to insert or update DHCP option in a pool. - /// - /// @param server_selector Server selector. - /// @param pool_start_address Lower bound address of the pool. - /// @param pool_end_address Upper bound address of the pool. - /// @param option Pointer to the option descriptor encapsulating the option. - void createUpdateOption6(const ServerSelector& server_selector, - const IOAddress& pool_start_address, - const IOAddress& pool_end_address, - const OptionDescriptorPtr& option) { - uint64_t pool_id = 0; - Pool6Ptr pool = getPool6(server_selector, pool_start_address, pool_end_address, pool_id); - if (!pool) { - isc_throw(BadValue, "no pool found for range of " << pool_start_address << " : " - << pool_end_address); - } - - createUpdateOption6(server_selector, Lease::TYPE_NA, pool_id, option, false); - } - - /// @brief Sends query to insert or update DHCP option in a pd pool. - /// - /// @param server_selector Server selector. - /// @param pd_pool_prefix Address part of the pd pool prefix. - /// @param pd_pool_prefix_length Length of the pd pool prefix. - /// @param option Pointer to the option descriptor encapsulating the option. - void createUpdateOption6(const ServerSelector& server_selector, - const asiolink::IOAddress& pd_pool_prefix, - const uint8_t pd_pool_prefix_length, - const OptionDescriptorPtr& option) { - uint64_t pd_pool_id = 0; - Pool6Ptr pd_pool = getPdPool6(server_selector, pd_pool_prefix, pd_pool_prefix_length, - pd_pool_id); - if (!pd_pool) { - isc_throw(BadValue, "no prefix delegation pool found for prefix " - << "of " << pd_pool_prefix << "/" - << static_cast(pd_pool_prefix_length)); - } - - createUpdateOption6(server_selector, Lease::TYPE_PD, pd_pool_id, option, false); - } - - /// @brief Sends query to insert or update DHCP option in an address - /// or prefix delegation pool. - /// - /// @param selector Server selector. - /// @param pool_type Pool type (Lease::TYPE_NA or Lease::TYPE_PD). - /// @param pool_id Identifier of the address or prefix delegation pool - /// the option belongs to. - /// @param option Pointer to the option descriptor encapsulating the option. - /// @param cascade_update Boolean value indicating whether the update is - /// performed as part of the owning element, e.g. subnet. - void createUpdateOption6(const ServerSelector& server_selector, - const Lease::Type& pool_type, - const uint64_t pool_id, - const OptionDescriptorPtr& option, - const bool cascade_update) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Sends query to insert or update DHCP option in a shared network. - /// - /// @param selector Server selector. - /// @param shared_network_name Name of the shared network the option - /// belongs to. - /// @param option Pointer to the option descriptor encapsulating the option. - /// @param cascade_update Boolean value indicating whether the update is - /// performed as part of the owning element, e.g. shared network. - void createUpdateOption6(const ServerSelector& server_selector, - const std::string& shared_network_name, - const OptionDescriptorPtr& option, - const bool cascade_update) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Sends query to insert or update option definition. - /// - /// @param server_selector Server selector. - /// @param option_def Pointer to the option definition to be inserted or updated. - void createUpdateOptionDef6(const ServerSelector& server_selector, - const OptionDefinitionPtr& option_def) { - - createUpdateOptionDef(server_selector, option_def, DHCP6_OPTION_SPACE, - PgSqlConfigBackendDHCPv6Impl::GET_OPTION_DEF6_CODE_SPACE, - PgSqlConfigBackendDHCPv6Impl::INSERT_OPTION_DEF6, - PgSqlConfigBackendDHCPv6Impl::UPDATE_OPTION_DEF6, - PgSqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION, - PgSqlConfigBackendDHCPv6Impl::INSERT_OPTION_DEF6_SERVER); - } - - /// @brief Sends query to delete option definition by code and - /// option space name. - /// - /// @param server_selector Server selector. - /// @param code Option code. - /// @param name Option name. - /// @return Number of deleted option definitions. - uint64_t deleteOptionDef6(const ServerSelector& server_selector, - const uint16_t code, - const std::string& space) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Deletes global option. - /// - /// @param server_selector Server selector. - /// @param code Code of the deleted option. - /// @param space Option space of the deleted option. - /// @return Number of deleted options. - uint64_t deleteOption6(const ServerSelector& server_selector, - const uint16_t code, - const std::string& space) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Deletes subnet level option. - /// - /// @param server_selector Server selector. - /// @param subnet_id Identifier of the subnet to which deleted option - /// belongs. - /// @param code Code of the deleted option. - /// @param space Option space of the deleted option. - /// @return Number of deleted options. - uint64_t deleteOption6(const ServerSelector& server_selector, - const SubnetID& subnet_id, - const uint16_t code, - const std::string& space) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Deletes pool level option. - /// - /// @param server_selector Server selector. - /// @param pool_start_address Lower bound pool address. - /// @param pool_end_address Upper bound pool address. - /// @param code Code of the deleted option. - /// @param space Option space of the deleted option. - /// @return Number of deleted options. - uint64_t deleteOption6(const db::ServerSelector& server_selector, - const IOAddress& pool_start_address, - const IOAddress& pool_end_address, - const uint16_t code, - const std::string& space) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Deletes pd pool level option. - /// - /// @param server_selector Server selector. - /// @param pd_pool_prefix Address part of the pd pool prefix. - /// @param pd_pool_prefix_length Length of the pd pool prefix. - /// @param code Code of the deleted option. - /// @param space Option space of the deleted option. - /// @return Number of deleted options. - uint64_t deleteOption6(const db::ServerSelector& server_selector, - const asiolink::IOAddress& pd_pool_prefix, - const uint8_t pd_pool_prefix_length, - const uint16_t code, - const std::string& space) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Deletes shared network level option. - /// - /// @param server_selector Server selector. - /// @param shared_network_name Name of the shared network which deleted - /// option belongs to - /// @param code Code of the deleted option. - /// @param space Option space of the deleted option. - /// @return Number of deleted options. - uint64_t deleteOption6(const db::ServerSelector& server_selector, - const std::string& shared_network_name, - const uint16_t code, - const std::string& space) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Deletes options belonging to a subnet from the database. - /// - /// @param server_selector Server selector. - /// @param subnet Pointer to the subnet for which options should be - /// deleted. - /// @return Number of deleted options. - uint64_t deleteOptions6(const ServerSelector& server_selector, const Subnet6Ptr& subnet) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Deletes options belonging to a shared network from the database. - /// - /// @param server_selector Server selector. - /// @param subnet Pointer to the subnet for which options should be - /// deleted. - /// @return Number of deleted options. - uint64_t - deleteOptions6(const ServerSelector& server_selector, const SharedNetwork6Ptr& shared_network) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Removes unassigned global parameters, global options and - /// option definitions. - /// - /// This function is called when one or more servers are deleted and - /// it is likely that there are some orphaned configuration elements - /// left in the database. This method removes those elements. - void purgeUnassignedConfig() { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Attempts to delete a server having a given tag. - /// - /// @param server_tag Tag of the server to be deleted. - /// @return Number of deleted servers. - /// @throw isc::InvalidOperation when trying to delete the logical - /// server 'all'. - uint64_t deleteServer6(const data::ServerTag& server_tag) { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Attempts to delete all servers. - /// - /// This method deletes all servers added by the user. It does not - /// delete the logical server 'all'. - /// - /// @return Number of deleted servers. - uint64_t deleteAllServers6() { - isc_throw(NotImplemented, "Not implemented yet."); - } - - /// @brief Attempts to reconnect the server to the config DB backend manager. - /// - /// This is a self-rescheduling function that attempts to reconnect to the - /// server's config DB backends after connectivity to one or more have been - /// lost. Upon entry it will attempt to reconnect via - /// @ref ConfigBackendDHCPv6Mgr.addBackend. - /// If this is successful, DHCP servicing is re-enabled and server returns - /// to normal operation. - /// - /// If reconnection fails and the maximum number of retries has not been - /// exhausted, it will schedule a call to itself to occur at the - /// configured retry interval. DHCP service remains disabled. - /// - /// If the maximum number of retries has been exhausted an error is logged - /// and the server shuts down. - /// - /// @param db_reconnect_ctl pointer to the ReconnectCtl containing the - /// configured reconnect parameters. - /// @return true if connection has been recovered, false otherwise. - static bool dbReconnect(ReconnectCtlPtr db_reconnect_ctl) { - // Invoke application layer connection lost callback. - if (!DatabaseConnection::invokeDbLostCallback(db_reconnect_ctl)) { - return (false); - } - - bool reopened = false; - - const std::string timer_name = db_reconnect_ctl->timerName(); - - // At least one connection was lost. - try { - auto srv_cfg = CfgMgr::instance().getCurrentCfg(); - auto config_ctl = srv_cfg->getConfigControlInfo(); - // Iterate over the configured DBs and instantiate them. - for (auto db : config_ctl->getConfigDatabases()) { - const std::string& access = db.getAccessString(); - auto parameters = db.getParameters(); - if (ConfigBackendDHCPv6Mgr::instance().delBackend(parameters["type"], access, - true)) { - ConfigBackendDHCPv6Mgr::instance().addBackend(db.getAccessString()); - } - } - - reopened = true; - } catch (const std::exception& ex) { - LOG_ERROR(pgsql_cb_logger, PGSQL_CB_RECONNECT_ATTEMPT_FAILED6).arg(ex.what()); - } - - if (reopened) { - // Cancel the timer. - if (TimerMgr::instance()->isTimerRegistered(timer_name)) { - TimerMgr::instance()->unregisterTimer(timer_name); - } - - // Invoke application layer connection recovered callback. - if (!DatabaseConnection::invokeDbRecoveredCallback(db_reconnect_ctl)) { - return (false); - } - } else { - if (!db_reconnect_ctl->checkRetries()) { - // We're out of retries, log it and initiate shutdown. - LOG_ERROR(pgsql_cb_logger, PGSQL_CB_RECONNECT_FAILED6) - .arg(db_reconnect_ctl->maxRetries()); - - // Cancel the timer. - if (TimerMgr::instance()->isTimerRegistered(timer_name)) { - TimerMgr::instance()->unregisterTimer(timer_name); - } - - // Invoke application layer connection failed callback. - DatabaseConnection::invokeDbFailedCallback(db_reconnect_ctl); - - return (false); - } - - LOG_INFO(pgsql_cb_logger, PGSQL_CB_RECONNECT_ATTEMPT_SCHEDULE6) - .arg(db_reconnect_ctl->maxRetries() - db_reconnect_ctl->retriesLeft() + 1) - .arg(db_reconnect_ctl->maxRetries()) - .arg(db_reconnect_ctl->retryInterval()); - - // Start the timer. - if (!TimerMgr::instance()->isTimerRegistered(timer_name)) { - TimerMgr::instance()->registerTimer( - timer_name, - std::bind(&PgSqlConfigBackendDHCPv6Impl::dbReconnect, db_reconnect_ctl), - db_reconnect_ctl->retryInterval(), asiolink::IntervalTimer::ONE_SHOT); - } - TimerMgr::instance()->setup(timer_name); - } - - return (true); - } -}; - -namespace { - -/// @brief Array of tagged statements. -typedef std::array - PgSqlTaggedStatementArray; - -/// @brief Prepared Postgres statements used by the backend to insert and -/// retrieve data from the database. -PgSqlTaggedStatementArray tagged_statements = { { - { 4, { OID_INT8, OID_INT8, OID_INT8, OID_INT8 }, "CREATE_AUDIT_REVISION", - "CALL createAuditRevisionDHCP6(?, ?, ?, ?)" - }, - - // Select global parameter by name. - { 1, { OID_VARCHAR }, "GET_GLOBAL_PARAMETER6", - PGSQL_GET_GLOBAL_PARAMETER(dhcp6, AND g.name = ?) - } -}}; - -#if 0 - // Select all global parameters. - { PgSqlConfigBackendDHCPv6Impl::GET_ALL_GLOBAL_PARAMETERS6, - PGSQL_GET_GLOBAL_PARAMETER(dhcp6) - }, - - // Select modified global parameters. - { PgSqlConfigBackendDHCPv6Impl::GET_MODIFIED_GLOBAL_PARAMETERS6, - PGSQL_GET_GLOBAL_PARAMETER(dhcp6, AND g.modification_ts >= ?) - }, - - // Delete all global parameters which are unassigned to any servers. - { PgSqlConfigBackendDHCPv6Impl::DELETE_ALL_GLOBAL_PARAMETERS6_UNASSIGNED, - PGSQL_DELETE_GLOBAL_PARAMETER_UNASSIGNED(dhcp6) - }, - - // Select subnet by id. - { PgSqlConfigBackendDHCPv6Impl::GET_SUBNET6_ID_NO_TAG, - PGSQL_GET_SUBNET6_NO_TAG(WHERE s.subnet_id = ?) - }, - - // Select subnet by id without specifying server tags. - { PgSqlConfigBackendDHCPv6Impl::GET_SUBNET6_ID_ANY, - PGSQL_GET_SUBNET6_ANY(WHERE s.subnet_id = ?) - }, - - // Select unassigned subnet by id. - { PgSqlConfigBackendDHCPv6Impl::GET_SUBNET6_ID_UNASSIGNED, - PGSQL_GET_SUBNET6_UNASSIGNED(AND s.subnet_id = ?) - }, - - // Select subnet by prefix. - { PgSqlConfigBackendDHCPv6Impl::GET_SUBNET6_PREFIX_NO_TAG, - PGSQL_GET_SUBNET6_NO_TAG(WHERE s.subnet_prefix = ?) - }, - - // Select subnet by prefix without specifying server tags. - { PgSqlConfigBackendDHCPv6Impl::GET_SUBNET6_PREFIX_ANY, - PGSQL_GET_SUBNET6_ANY(WHERE s.subnet_prefix = ?) - }, - - // Select unassigned subnet by prefix. - { PgSqlConfigBackendDHCPv6Impl::GET_SUBNET6_PREFIX_UNASSIGNED, - PGSQL_GET_SUBNET6_UNASSIGNED(AND s.subnet_prefix = ?) - }, - - // Select all subnets. - { PgSqlConfigBackendDHCPv6Impl::GET_ALL_SUBNETS6, - PGSQL_GET_SUBNET6_NO_TAG() - }, - - // Select all unassigned subnets. - { PgSqlConfigBackendDHCPv6Impl::GET_ALL_SUBNETS6_UNASSIGNED, - PGSQL_GET_SUBNET6_UNASSIGNED() - }, - - // Select subnets having modification time later than X. - { PgSqlConfigBackendDHCPv6Impl::GET_MODIFIED_SUBNETS6, - PGSQL_GET_SUBNET6_NO_TAG(WHERE s.modification_ts >= ?) - }, - - // Select modified and unassigned subnets. - { PgSqlConfigBackendDHCPv6Impl::GET_MODIFIED_SUBNETS6_UNASSIGNED, - PGSQL_GET_SUBNET6_UNASSIGNED(AND s.modification_ts >= ?) - }, - - // Select subnets belonging to a shared network. - { PgSqlConfigBackendDHCPv6Impl::GET_SHARED_NETWORK_SUBNETS6, - PGSQL_GET_SUBNET6_ANY(WHERE s.shared_network_name = ?) - }, - - // Select pool by address range for a server. - { PgSqlConfigBackendDHCPv6Impl::GET_POOL6_RANGE, - PGSQL_GET_POOL6_RANGE_WITH_TAG(WHERE (srv.tag = ? OR srv.id = 1) AND p.start_address = ? \ - AND p.end_address = ?) - }, - - // Select pool by address range for any server. - { PgSqlConfigBackendDHCPv6Impl::GET_POOL6_RANGE_ANY, - PGSQL_GET_POOL6_RANGE_NO_TAG(WHERE p.start_address = ? AND p.end_address = ?) - }, - - // Select prefix delegation pool for a server. - { PgSqlConfigBackendDHCPv6Impl::GET_PD_POOL, - PGSQL_GET_PD_POOL_WITH_TAG(WHERE (srv.tag = ? OR srv.id = 1) \ - AND p.prefix = ? AND p.prefix_length = ?) - }, - - // Select prefix delegation pool for any server. - { PgSqlConfigBackendDHCPv6Impl::GET_PD_POOL_ANY, - PGSQL_GET_PD_POOL_NO_TAG(WHERE p.prefix = ? AND p.prefix_length = ?) - }, - - // Select shared network by name. - { PgSqlConfigBackendDHCPv6Impl::GET_SHARED_NETWORK6_NAME_NO_TAG, - PGSQL_GET_SHARED_NETWORK6_NO_TAG(WHERE n.name = ?) - }, - - // Select shared network by name without specifying server tags. - { PgSqlConfigBackendDHCPv6Impl::GET_SHARED_NETWORK6_NAME_ANY, - PGSQL_GET_SHARED_NETWORK6_ANY(WHERE n.name = ?) - }, - - // Select unassigned shared network by name. - { PgSqlConfigBackendDHCPv6Impl::GET_SHARED_NETWORK6_NAME_UNASSIGNED, - PGSQL_GET_SHARED_NETWORK6_UNASSIGNED(AND n.name = ?) - }, - - // Select all shared networks. - { PgSqlConfigBackendDHCPv6Impl::GET_ALL_SHARED_NETWORKS6, - PGSQL_GET_SHARED_NETWORK6_NO_TAG() - }, - - // Select all unassigned shared networks. - { PgSqlConfigBackendDHCPv6Impl::GET_ALL_SHARED_NETWORKS6_UNASSIGNED, - PGSQL_GET_SHARED_NETWORK6_UNASSIGNED() - }, - - // Select modified shared networks. - { PgSqlConfigBackendDHCPv6Impl::GET_MODIFIED_SHARED_NETWORKS6, - PGSQL_GET_SHARED_NETWORK6_NO_TAG(WHERE n.modification_ts >= ?) - }, - - // Select modified and unassigned shared networks. - { PgSqlConfigBackendDHCPv6Impl::GET_MODIFIED_SHARED_NETWORKS6_UNASSIGNED, - PGSQL_GET_SHARED_NETWORK6_UNASSIGNED(AND n.modification_ts >= ?) - }, - - // Retrieves option definition by code and space. - { PgSqlConfigBackendDHCPv6Impl::GET_OPTION_DEF6_CODE_SPACE, - PGSQL_GET_OPTION_DEF(dhcp6, AND d.code = ? AND d.space = ?) - }, - - // Retrieves all option definitions. - { PgSqlConfigBackendDHCPv6Impl::GET_ALL_OPTION_DEFS6, - PGSQL_GET_OPTION_DEF(dhcp6) - }, - - // Retrieves modified option definitions. - { PgSqlConfigBackendDHCPv6Impl::GET_MODIFIED_OPTION_DEFS6, - PGSQL_GET_OPTION_DEF(dhcp6, AND d.modification_ts >= ?) - }, - - // Retrieves global option by code and space. - { PgSqlConfigBackendDHCPv6Impl::GET_OPTION6_CODE_SPACE, - PGSQL_GET_OPTION6(AND o.scope_id = 0 AND o.code = ? AND o.space = ?) - }, - - // Retrieves all global options. - { PgSqlConfigBackendDHCPv6Impl::GET_ALL_OPTIONS6, - PGSQL_GET_OPTION6(AND o.scope_id = 0) - }, - - // Retrieves modified options. - { PgSqlConfigBackendDHCPv6Impl::GET_MODIFIED_OPTIONS6, - PGSQL_GET_OPTION6(AND o.scope_id = 0 AND o.modification_ts >= ?) - }, - - // Retrieves an option for a given subnet, option code and space. - { PgSqlConfigBackendDHCPv6Impl::GET_OPTION6_SUBNET_ID_CODE_SPACE, - PGSQL_GET_OPTION6(AND o.scope_id = 1 AND o.dhcp6_subnet_id = ? AND o.code = ? AND o.space = ?) - }, - - // Retrieves an option for a given pool, option code and space. - { PgSqlConfigBackendDHCPv6Impl::GET_OPTION6_POOL_ID_CODE_SPACE, - PGSQL_GET_OPTION6(AND o.scope_id = 5 AND o.pool_id = ? AND o.code = ? AND o.space = ?) - }, - - // Retrieves an option for a given pd pool, option code and space. - { PgSqlConfigBackendDHCPv6Impl::GET_OPTION6_PD_POOL_ID_CODE_SPACE, - PGSQL_GET_OPTION6(AND o.scope_id = 6 AND o.pd_pool_id = ? AND o.code = ? AND o.space = ?) - }, - - // Retrieves an option for a given shared network, option code and space. - { PgSqlConfigBackendDHCPv6Impl::GET_OPTION6_SHARED_NETWORK_CODE_SPACE, - PGSQL_GET_OPTION6(AND o.scope_id = 4 AND o.shared_network_name = ? AND o.code = ? AND o.space = ?) - }, - - // Retrieves the most recent audit entries. - { PgSqlConfigBackendDHCPv6Impl::GET_AUDIT_ENTRIES6_TIME, - PGSQL_GET_AUDIT_ENTRIES_TIME(dhcp6) - }, - - // Retrieves a server by tag. - { PgSqlConfigBackendDHCPv6Impl::GET_SERVER6, - PGSQL_GET_SERVER(dhcp6) - }, - - // Retrieves all servers. - { PgSqlConfigBackendDHCPv6Impl::GET_ALL_SERVERS6, - PGSQL_GET_ALL_SERVERS(dhcp6) - }, - - // Insert global parameter. - { PgSqlConfigBackendDHCPv6Impl::INSERT_GLOBAL_PARAMETER6, - PGSQL_INSERT_GLOBAL_PARAMETER(dhcp6) - }, - - // Insert association of the global parameter with a server. - { PgSqlConfigBackendDHCPv6Impl::INSERT_GLOBAL_PARAMETER6_SERVER, - PGSQL_INSERT_GLOBAL_PARAMETER_SERVER(dhcp6) - }, - - // Insert a subnet. - { PgSqlConfigBackendDHCPv6Impl::INSERT_SUBNET6, - "INSERT INTO dhcp6_subnet(" - " subnet_id," - " 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," - " reservations_global," - " shared_network_name," - " user_context," - " valid_lifetime," - " min_valid_lifetime," - " max_valid_lifetime," - " calculate_tee_times," - " t1_percent," - " t2_percent," - " interface_id," - " ddns_send_updates," - " ddns_override_no_update," - " ddns_override_client_update," - " ddns_replace_client_name," - " ddns_generated_prefix," - " ddns_qualifying_suffix," - " reservations_in_subnet," - " reservations_out_of_pool," - " cache_threshold," - " cache_max_age" - ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?," - " ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" }, - - // Insert association of the subnet with a server. - { PgSqlConfigBackendDHCPv6Impl::INSERT_SUBNET6_SERVER, - PGSQL_INSERT_SUBNET_SERVER(dhcp6) - }, - - // Insert pool for a subnet. - { PgSqlConfigBackendDHCPv6Impl::INSERT_POOL6, - PGSQL_INSERT_POOL(dhcp6) - }, - - // Insert pd pool for a subnet. - { PgSqlConfigBackendDHCPv6Impl::INSERT_PD_POOL, - PGSQL_INSERT_PD_POOL() - }, - - // Insert a shared network. - { PgSqlConfigBackendDHCPv6Impl::INSERT_SHARED_NETWORK6, - "INSERT INTO dhcp6_shared_network(" - " name," - " client_class," - " interface," - " modification_ts," - " preferred_lifetime," - " min_preferred_lifetime," - " max_preferred_lifetime," - " rapid_commit," - " rebind_timer," - " relay," - " renew_timer," - " require_client_classes," - " reservations_global," - " user_context," - " valid_lifetime," - " min_valid_lifetime," - " max_valid_lifetime," - " calculate_tee_times," - " t1_percent," - " t2_percent," - " interface_id," - " ddns_send_updates," - " ddns_override_no_update," - " ddns_override_client_update," - " ddns_replace_client_name," - " ddns_generated_prefix," - " ddns_qualifying_suffix," - " reservations_in_subnet," - " reservations_out_of_pool," - " cache_threshold," - " cache_max_age" - ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?," - " ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" }, - - // Insert association of the shared network with a server. - { PgSqlConfigBackendDHCPv6Impl::INSERT_SHARED_NETWORK6_SERVER, - PGSQL_INSERT_SHARED_NETWORK_SERVER(dhcp6) - }, - - // Insert option definition. - { PgSqlConfigBackendDHCPv6Impl::INSERT_OPTION_DEF6, - PGSQL_INSERT_OPTION_DEF(dhcp6) - }, - - // Insert association of the option definition with a server. - { PgSqlConfigBackendDHCPv6Impl::INSERT_OPTION_DEF6_SERVER, - PGSQL_INSERT_OPTION_DEF_SERVER(dhcp6) - }, - - // Insert subnet specific option. - { PgSqlConfigBackendDHCPv6Impl::INSERT_OPTION6, - PGSQL_INSERT_OPTION6() - }, - - // Insert association of the DHCP option with a server. - { PgSqlConfigBackendDHCPv6Impl::INSERT_OPTION6_SERVER, - PGSQL_INSERT_OPTION_SERVER(dhcp6) - }, - - // Insert server with server tag and description. - { PgSqlConfigBackendDHCPv6Impl::INSERT_SERVER6, - PGSQL_INSERT_SERVER(dhcp6) - }, - - // Update existing global parameter. - { PgSqlConfigBackendDHCPv6Impl::UPDATE_GLOBAL_PARAMETER6, - PGSQL_UPDATE_GLOBAL_PARAMETER(dhcp6) - }, - - // Update existing subnet. - { PgSqlConfigBackendDHCPv6Impl::UPDATE_SUBNET6, - "UPDATE dhcp6_subnet SET" - " subnet_id = ?," - " 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 = ?," - " reservations_global = ?," - " shared_network_name = ?," - " user_context = ?," - " valid_lifetime = ?," - " min_valid_lifetime = ?," - " max_valid_lifetime = ?," - " calculate_tee_times = ?," - " t1_percent = ?," - " t2_percent = ?," - " interface_id = ?," - " ddns_send_updates = ?," - " ddns_override_no_update = ?," - " ddns_override_client_update = ?," - " ddns_replace_client_name = ?," - " ddns_generated_prefix = ?," - " ddns_qualifying_suffix = ?," - " reservations_in_subnet = ?," - " reservations_out_of_pool = ?," - " cache_threshold = ?," - " cache_max_age = ? " - "WHERE subnet_id = ? OR subnet_prefix = ?" }, - - // Update existing shared network. - { PgSqlConfigBackendDHCPv6Impl::UPDATE_SHARED_NETWORK6, - "UPDATE dhcp6_shared_network SET" - " name = ?," - " client_class = ?," - " interface = ?," - " modification_ts = ?," - " preferred_lifetime = ?," - " min_preferred_lifetime = ?," - " max_preferred_lifetime = ?," - " rapid_commit = ?," - " rebind_timer = ?," - " relay = ?," - " renew_timer = ?," - " require_client_classes = ?," - " reservations_global = ?," - " user_context = ?," - " valid_lifetime = ?," - " min_valid_lifetime = ?," - " max_valid_lifetime = ?," - " calculate_tee_times = ?," - " t1_percent = ?," - " t2_percent = ?," - " interface_id = ?," - " ddns_send_updates = ?," - " ddns_override_no_update = ?," - " ddns_override_client_update = ?," - " ddns_replace_client_name = ?," - " ddns_generated_prefix = ?," - " ddns_qualifying_suffix = ?," - " reservations_in_subnet = ?," - " reservations_out_of_pool = ?," - " cache_threshold = ?," - " cache_max_age = ? " - "WHERE name = ?" }, - - // Update existing option definition. - { PgSqlConfigBackendDHCPv6Impl::UPDATE_OPTION_DEF6, - PGSQL_UPDATE_OPTION_DEF(dhcp6) - }, - - // Update existing global option. - { PgSqlConfigBackendDHCPv6Impl::UPDATE_OPTION6, - PGSQL_UPDATE_OPTION6_WITH_TAG(AND o.scope_id = 0 AND o.code = ? AND o.space = ?) - }, - - // Update existing subnet level option. - { PgSqlConfigBackendDHCPv6Impl::UPDATE_OPTION6_SUBNET_ID, - PGSQL_UPDATE_OPTION6_NO_TAG(o.scope_id = 1 AND o.dhcp6_subnet_id = ? AND o.code = ? AND o.space = ?) - }, - - // Update existing pool level option. - { PgSqlConfigBackendDHCPv6Impl::UPDATE_OPTION6_POOL_ID, - PGSQL_UPDATE_OPTION6_NO_TAG(o.scope_id = 5 AND o.pool_id = ? AND o.code = ? AND o.space = ?) - }, - - // Update existing pd pool level option. - { PgSqlConfigBackendDHCPv6Impl::UPDATE_OPTION6_PD_POOL_ID, - PGSQL_UPDATE_OPTION6_NO_TAG(o.scope_id = 6 AND o.pd_pool_id = ? AND o.code = ? AND o.space = ?) - }, - - // Update existing shared network level option. - { PgSqlConfigBackendDHCPv6Impl::UPDATE_OPTION6_SHARED_NETWORK, - PGSQL_UPDATE_OPTION6_NO_TAG(o.scope_id = 4 AND o.shared_network_name = ? AND o.code = ? AND o.space = ?) - }, - - // Update existing server, e.g. server description. - { PgSqlConfigBackendDHCPv6Impl::UPDATE_SERVER6, - PGSQL_UPDATE_SERVER(dhcp6) - }, - - // Delete global parameter by name. - { PgSqlConfigBackendDHCPv6Impl::DELETE_GLOBAL_PARAMETER6, - PGSQL_DELETE_GLOBAL_PARAMETER(dhcp6, AND g.name = ?) - }, - - // Delete all global parameters. - { PgSqlConfigBackendDHCPv6Impl::DELETE_ALL_GLOBAL_PARAMETERS6, - PGSQL_DELETE_GLOBAL_PARAMETER(dhcp6) - }, - - // Delete subnet by id with specifying server tag. - { PgSqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_ID_WITH_TAG, - PGSQL_DELETE_SUBNET_WITH_TAG(dhcp6, AND s.subnet_id = ?) - }, - - // Delete subnet by id without specifying server tag. - { PgSqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_ID_ANY, - PGSQL_DELETE_SUBNET_ANY(dhcp6, WHERE s.subnet_id = ?) - }, - - // Delete subnet by prefix with specifying server tag. - { PgSqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_PREFIX_WITH_TAG, - PGSQL_DELETE_SUBNET_WITH_TAG(dhcp6, AND s.subnet_prefix = ?) - }, - - // Delete subnet by prefix without specifying server tag. - { PgSqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_PREFIX_ANY, - PGSQL_DELETE_SUBNET_ANY(dhcp6, WHERE s.subnet_prefix = ?) - }, - - // Delete all subnets. - { PgSqlConfigBackendDHCPv6Impl::DELETE_ALL_SUBNETS6, - PGSQL_DELETE_SUBNET_WITH_TAG(dhcp6) - }, - - // Delete all unassigned subnets. - { PgSqlConfigBackendDHCPv6Impl::DELETE_ALL_SUBNETS6_UNASSIGNED, - PGSQL_DELETE_SUBNET_UNASSIGNED(dhcp6) - }, - - // Delete all subnets for a shared network. - { PgSqlConfigBackendDHCPv6Impl::DELETE_ALL_SUBNETS6_SHARED_NETWORK_NAME, - PGSQL_DELETE_SUBNET_ANY(dhcp6, WHERE s.shared_network_name = ?) - }, - - // Delete associations of a subnet with server. - { PgSqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_SERVER, - PGSQL_DELETE_SUBNET_SERVER(dhcp6), - }, - - // Delete pools for a subnet. - { PgSqlConfigBackendDHCPv6Impl::DELETE_POOLS6, - PGSQL_DELETE_POOLS(dhcp6) - }, - - // Delete pd pools for a subnet. - { PgSqlConfigBackendDHCPv6Impl::DELETE_PD_POOLS, - PGSQL_DELETE_PD_POOLS() - }, - - // Delete shared network by name with specifying server tag. - { PgSqlConfigBackendDHCPv6Impl::DELETE_SHARED_NETWORK6_NAME_WITH_TAG, - PGSQL_DELETE_SHARED_NETWORK_WITH_TAG(dhcp6, AND n.name = ?) - }, - - // Delete shared network by name without specifying server tag. - { PgSqlConfigBackendDHCPv6Impl::DELETE_SHARED_NETWORK6_NAME_ANY, - PGSQL_DELETE_SHARED_NETWORK_ANY(dhcp6, WHERE n.name = ?) - }, - - // Delete all shared networks. - { PgSqlConfigBackendDHCPv6Impl::DELETE_ALL_SHARED_NETWORKS6, - PGSQL_DELETE_SHARED_NETWORK_WITH_TAG(dhcp6) - }, - - // Delete all unassigned shared networks. - { PgSqlConfigBackendDHCPv6Impl::DELETE_ALL_SHARED_NETWORKS6_UNASSIGNED, - PGSQL_DELETE_SHARED_NETWORK_UNASSIGNED(dhcp6) - }, - - // Delete associations of a shared network with server. - { PgSqlConfigBackendDHCPv6Impl::DELETE_SHARED_NETWORK6_SERVER, - PGSQL_DELETE_SHARED_NETWORK_SERVER(dhcp6) - }, - - // Delete option definition. - { PgSqlConfigBackendDHCPv6Impl::DELETE_OPTION_DEF6_CODE_NAME, - PGSQL_DELETE_OPTION_DEF(dhcp6, AND code = ? AND space = ?) - }, - - // Delete all option definitions. - { PgSqlConfigBackendDHCPv6Impl::DELETE_ALL_OPTION_DEFS6, - PGSQL_DELETE_OPTION_DEF(dhcp6) - }, - - // Delete all option definitions which are assigned to no servers. - { PgSqlConfigBackendDHCPv6Impl::DELETE_ALL_OPTION_DEFS6_UNASSIGNED, - PGSQL_DELETE_OPTION_DEF_UNASSIGNED(dhcp6) - }, - - // Delete single global option. - { PgSqlConfigBackendDHCPv6Impl::DELETE_OPTION6, - PGSQL_DELETE_OPTION_WITH_TAG(dhcp6, AND o.scope_id = 0 AND o.code = ? AND o.space = ?) - }, - - // Delete all global options which are unassigned to any servers. - { PgSqlConfigBackendDHCPv6Impl::DELETE_ALL_GLOBAL_OPTIONS6_UNASSIGNED, - PGSQL_DELETE_OPTION_UNASSIGNED(dhcp6, AND o.scope_id = 0) - }, - - // Delete single option from a subnet. - { PgSqlConfigBackendDHCPv6Impl::DELETE_OPTION6_SUBNET_ID, - PGSQL_DELETE_OPTION_NO_TAG(dhcp6, - WHERE o.scope_id = 1 AND o.dhcp6_subnet_id = ? AND o.code = ? AND o.space = ?) - }, - - // Delete single option from a pool. - { PgSqlConfigBackendDHCPv6Impl::DELETE_OPTION6_POOL_RANGE, - PGSQL_DELETE_OPTION_POOL_RANGE(dhcp6, o.scope_id = 5 AND o.code = ? AND o.space = ?) - }, - - // Delete single option from a pd pool. - { PgSqlConfigBackendDHCPv6Impl::DELETE_OPTION6_PD_POOL, - PGSQL_DELETE_OPTION_PD_POOL(o.scope_id = 6 AND o.code = ? AND o.space = ?) - }, - - // Delete single option from a shared network. - { PgSqlConfigBackendDHCPv6Impl::DELETE_OPTION6_SHARED_NETWORK, - PGSQL_DELETE_OPTION_NO_TAG(dhcp6, - WHERE o.scope_id = 4 AND o.shared_network_name = ? AND o.code = ? AND o.space = ?) - }, - - // Delete options belonging to a subnet. - { PgSqlConfigBackendDHCPv6Impl::DELETE_OPTIONS6_SUBNET_ID_PREFIX, - PGSQL_DELETE_OPTION_SUBNET_ID_PREFIX(dhcp6) - }, - - // Delete options belonging to a shared_network. - { PgSqlConfigBackendDHCPv6Impl::DELETE_OPTIONS6_SHARED_NETWORK, - PGSQL_DELETE_OPTION_NO_TAG(dhcp6, WHERE o.scope_id = 4 AND o.shared_network_name = ?) - }, - - // Delete a server by tag. - { PgSqlConfigBackendDHCPv6Impl::DELETE_SERVER6, - PGSQL_DELETE_SERVER(dhcp6) - }, - - // Deletes all servers except logical server 'all'. - { PgSqlConfigBackendDHCPv6Impl::DELETE_ALL_SERVERS6, - PGSQL_DELETE_ALL_SERVERS(dhcp6) - } -} -}; -#endif - -}; // end anonymous namespace - -PgSqlConfigBackendDHCPv6Impl::PgSqlConfigBackendDHCPv6Impl( - const DatabaseConnection::ParameterMap& parameters) - : PgSqlConfigBackendImpl(parameters, &PgSqlConfigBackendDHCPv6Impl::dbReconnect) { - // Prepare query statements. Those are will be only used to retrieve - // information from the database, so they can be used even if the - // database is read only for the current user. - conn_.prepareStatements(tagged_statements.begin(), tagged_statements.end()); - // tagged_statements.begin() + WRITE_STMTS_BEGIN); - - // Create unique timer name per instance. - timer_name_ = "PgSqlConfigBackend6["; - timer_name_ += boost::lexical_cast(reinterpret_cast(this)); - timer_name_ += "]DbReconnectTimer"; - - // Create ReconnectCtl for this connection. - conn_.makeReconnectCtl(timer_name_); -} - -PgSqlConfigBackendDHCPv6Impl::~PgSqlConfigBackendDHCPv6Impl() { -} - -PgSqlConfigBackendDHCPv6::PgSqlConfigBackendDHCPv6( - const DatabaseConnection::ParameterMap& parameters) - : impl_(new PgSqlConfigBackendDHCPv6Impl(parameters)), base_impl_(impl_) { -} - -bool -PgSqlConfigBackendDHCPv6::isUnusable() { - return (impl_->conn_.isUnusable()); -} - -Subnet6Ptr -PgSqlConfigBackendDHCPv6::getSubnet6(const ServerSelector& server_selector, - const std::string& subnet_prefix) const { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_SUBNET6_BY_PREFIX) - .arg(subnet_prefix); - return (impl_->getSubnet6(server_selector, subnet_prefix)); -} - -Subnet6Ptr -PgSqlConfigBackendDHCPv6::getSubnet6(const ServerSelector& server_selector, - const SubnetID& subnet_id) const { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_SUBNET6_BY_SUBNET_ID).arg(subnet_id); - return (impl_->getSubnet6(server_selector, subnet_id)); -} - -Subnet6Collection -PgSqlConfigBackendDHCPv6::getAllSubnets6(const ServerSelector& server_selector) const { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_ALL_SUBNETS6); - Subnet6Collection subnets; - impl_->getAllSubnets6(server_selector, subnets); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_ALL_SUBNETS6_RESULT) - .arg(subnets.size()); - return (subnets); -} - -Subnet6Collection -PgSqlConfigBackendDHCPv6::getModifiedSubnets6( - const ServerSelector& server_selector, - const boost::posix_time::ptime& modification_time) const { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_MODIFIED_SUBNETS6) - .arg(util::ptimeToText(modification_time)); - Subnet6Collection subnets; - impl_->getModifiedSubnets6(server_selector, modification_time, subnets); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_MODIFIED_SUBNETS6_RESULT) - .arg(subnets.size()); - return (subnets); -} - -Subnet6Collection -PgSqlConfigBackendDHCPv6::getSharedNetworkSubnets6(const ServerSelector& /* server_selector */, - const std::string& shared_network_name) const { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_SHARED_NETWORK_SUBNETS6) - .arg(shared_network_name); - Subnet6Collection subnets; - impl_->getSharedNetworkSubnets6(ServerSelector::ANY(), shared_network_name, subnets); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_SHARED_NETWORK_SUBNETS6_RESULT) - .arg(subnets.size()); - return (subnets); -} - -SharedNetwork6Ptr -PgSqlConfigBackendDHCPv6::getSharedNetwork6(const ServerSelector& server_selector, - const std::string& name) const { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_SHARED_NETWORK6).arg(name); - return (impl_->getSharedNetwork6(server_selector, name)); -} - -SharedNetwork6Collection -PgSqlConfigBackendDHCPv6::getAllSharedNetworks6(const ServerSelector& server_selector) const { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_ALL_SHARED_NETWORKS6); - SharedNetwork6Collection shared_networks; - impl_->getAllSharedNetworks6(server_selector, shared_networks); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_ALL_SHARED_NETWORKS6_RESULT) - .arg(shared_networks.size()); - return (shared_networks); -} - -SharedNetwork6Collection -PgSqlConfigBackendDHCPv6::getModifiedSharedNetworks6( - const ServerSelector& server_selector, - const boost::posix_time::ptime& modification_time) const { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_MODIFIED_SHARED_NETWORKS6) - .arg(util::ptimeToText(modification_time)); - SharedNetwork6Collection shared_networks; - impl_->getModifiedSharedNetworks6(server_selector, modification_time, shared_networks); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_MODIFIED_SHARED_NETWORKS6_RESULT) - .arg(shared_networks.size()); - return (shared_networks); -} - -OptionDefinitionPtr -PgSqlConfigBackendDHCPv6::getOptionDef6(const ServerSelector& server_selector, - const uint16_t code, - const std::string& space) const { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_OPTION_DEF6).arg(code).arg(space); - return (impl_->getOptionDef(PgSqlConfigBackendDHCPv6Impl::GET_OPTION_DEF6_CODE_SPACE, - server_selector, code, space)); -} - -OptionDefContainer -PgSqlConfigBackendDHCPv6::getAllOptionDefs6(const ServerSelector& server_selector) const { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_ALL_OPTION_DEFS6); - OptionDefContainer option_defs; - impl_->getAllOptionDefs(PgSqlConfigBackendDHCPv6Impl::GET_ALL_OPTION_DEFS6, server_selector, - option_defs); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_ALL_OPTION_DEFS6_RESULT) - .arg(option_defs.size()); - return (option_defs); -} - -OptionDefContainer -PgSqlConfigBackendDHCPv6::getModifiedOptionDefs6( - const ServerSelector& server_selector, - const boost::posix_time::ptime& modification_time) const { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_MODIFIED_OPTION_DEFS6) - .arg(util::ptimeToText(modification_time)); - OptionDefContainer option_defs; - impl_->getModifiedOptionDefs(PgSqlConfigBackendDHCPv6Impl::GET_MODIFIED_OPTION_DEFS6, - server_selector, modification_time, option_defs); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_MODIFIED_OPTION_DEFS6_RESULT) - .arg(option_defs.size()); - return (option_defs); -} - -OptionDescriptorPtr -PgSqlConfigBackendDHCPv6::getOption6(const ServerSelector& server_selector, - const uint16_t code, - const std::string& space) const { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_OPTION6).arg(code).arg(space); - return (impl_->getOption(PgSqlConfigBackendDHCPv6Impl::GET_OPTION6_CODE_SPACE, Option::V6, - server_selector, code, space)); -} - -OptionContainer -PgSqlConfigBackendDHCPv6::getAllOptions6(const ServerSelector& server_selector) const { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_ALL_OPTIONS6); - OptionContainer options = impl_->getAllOptions(PgSqlConfigBackendDHCPv6Impl::GET_ALL_OPTIONS6, - Option::V6, server_selector); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_ALL_OPTIONS6_RESULT) - .arg(options.size()); - return (options); -} - -OptionContainer -PgSqlConfigBackendDHCPv6::getModifiedOptions6( - const ServerSelector& server_selector, - const boost::posix_time::ptime& modification_time) const { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_MODIFIED_OPTIONS6) - .arg(util::ptimeToText(modification_time)); - OptionContainer options = - impl_->getModifiedOptions(PgSqlConfigBackendDHCPv6Impl::GET_MODIFIED_OPTIONS6, Option::V6, - server_selector, modification_time); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_MODIFIED_OPTIONS6_RESULT) - .arg(options.size()); - return (options); -} - -StampedValuePtr -PgSqlConfigBackendDHCPv6::getGlobalParameter6(const ServerSelector& server_selector, - const std::string& name) const { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_GLOBAL_PARAMETER6).arg(name); - return (impl_->getGlobalParameter6(server_selector, name)); -} - -StampedValueCollection -PgSqlConfigBackendDHCPv6::getAllGlobalParameters6(const ServerSelector& server_selector) const { - isc_throw(NotImplemented, "Not implemented yet."); -} - -StampedValueCollection -PgSqlConfigBackendDHCPv6::getModifiedGlobalParameters6( - const db::ServerSelector& server_selector, - const boost::posix_time::ptime& modification_time) const { - isc_throw(NotImplemented, "Not implemented yet."); -} - -AuditEntryCollection -PgSqlConfigBackendDHCPv6::getRecentAuditEntries(const db::ServerSelector& server_selector, - const boost::posix_time::ptime& modification_time, - const uint64_t& modification_id) const { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_RECENT_AUDIT_ENTRIES6) - .arg(util::ptimeToText(modification_time)) - .arg(modification_id); - AuditEntryCollection audit_entries; - impl_->getRecentAuditEntries(PgSqlConfigBackendDHCPv6Impl::GET_AUDIT_ENTRIES6_TIME, - server_selector, modification_time, modification_id, - audit_entries); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_RECENT_AUDIT_ENTRIES6_RESULT) - .arg(audit_entries.size()); - return (audit_entries); -} - -ServerCollection -PgSqlConfigBackendDHCPv6::getAllServers6() const { - ServerCollection servers; - - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_ALL_SERVERS6); - impl_->getAllServers(PgSqlConfigBackendDHCPv6Impl::GET_ALL_SERVERS6, servers); - - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_ALL_SERVERS6_RESULT) - .arg(servers.size()); - return (servers); -} - -ServerPtr -PgSqlConfigBackendDHCPv6::getServer6(const data::ServerTag& server_tag) const { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_SERVER6).arg(server_tag.get()); - return (impl_->getServer(PgSqlConfigBackendDHCPv6Impl::GET_SERVER6, server_tag)); -} - -void -PgSqlConfigBackendDHCPv6::createUpdateSubnet6(const ServerSelector& server_selector, - const Subnet6Ptr& subnet) { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_CREATE_UPDATE_SUBNET6).arg(subnet); - impl_->createUpdateSubnet6(server_selector, subnet); -} - -void -PgSqlConfigBackendDHCPv6::createUpdateSharedNetwork6(const ServerSelector& server_selector, - const SharedNetwork6Ptr& shared_network) { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_CREATE_UPDATE_SHARED_NETWORK6) - .arg(shared_network->getName()); - impl_->createUpdateSharedNetwork6(server_selector, shared_network); -} - -void -PgSqlConfigBackendDHCPv6::createUpdateOptionDef6(const ServerSelector& server_selector, - const OptionDefinitionPtr& option_def) { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_CREATE_UPDATE_OPTION_DEF6) - .arg(option_def->getName()) - .arg(option_def->getCode()); - impl_->createUpdateOptionDef6(server_selector, option_def); -} - -void -PgSqlConfigBackendDHCPv6::createUpdateOption6(const ServerSelector& server_selector, - const OptionDescriptorPtr& option) { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_CREATE_UPDATE_OPTION6); - impl_->createUpdateOption6(server_selector, option); -} - -void -PgSqlConfigBackendDHCPv6::createUpdateOption6(const db::ServerSelector& server_selector, - const std::string& shared_network_name, - const OptionDescriptorPtr& option) { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_CREATE_UPDATE_SHARED_NETWORK_OPTION6) - .arg(shared_network_name); - impl_->createUpdateOption6(server_selector, shared_network_name, option, false); -} - -void -PgSqlConfigBackendDHCPv6::createUpdateOption6(const ServerSelector& server_selector, - const SubnetID& subnet_id, - const OptionDescriptorPtr& option) { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_CREATE_UPDATE_BY_SUBNET_ID_OPTION6) - .arg(subnet_id); - impl_->createUpdateOption6(server_selector, subnet_id, option, false); -} - -void -PgSqlConfigBackendDHCPv6::createUpdateOption6(const ServerSelector& server_selector, - const asiolink::IOAddress& pool_start_address, - const asiolink::IOAddress& pool_end_address, - const OptionDescriptorPtr& option) { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_CREATE_UPDATE_BY_POOL_OPTION6) - .arg(pool_start_address.toText()) - .arg(pool_end_address.toText()); - impl_->createUpdateOption6(server_selector, pool_start_address, pool_end_address, option); -} - -void -PgSqlConfigBackendDHCPv6::createUpdateOption6(const ServerSelector& server_selector, - const asiolink::IOAddress& pd_pool_prefix, - const uint8_t pd_pool_prefix_length, - const OptionDescriptorPtr& option) { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_CREATE_UPDATE_BY_PREFIX_OPTION6) - .arg(pd_pool_prefix.toText()) - .arg(pd_pool_prefix_length); - impl_->createUpdateOption6(server_selector, pd_pool_prefix, pd_pool_prefix_length, option); -} - -void -PgSqlConfigBackendDHCPv6::createUpdateGlobalParameter6(const ServerSelector& server_selector, - const StampedValuePtr& value) { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_CREATE_UPDATE_GLOBAL_PARAMETER6) - .arg(value->getName()); - impl_->createUpdateGlobalParameter6(server_selector, value); -} - -void -PgSqlConfigBackendDHCPv6::createUpdateServer6(const ServerPtr& server) { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_CREATE_UPDATE_SERVER6) - .arg(server->getServerTagAsText()); - impl_->createUpdateServer(PgSqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION, - PgSqlConfigBackendDHCPv6Impl::INSERT_SERVER6, - PgSqlConfigBackendDHCPv6Impl::UPDATE_SERVER6, server); -} - -uint64_t -PgSqlConfigBackendDHCPv6::deleteSubnet6(const ServerSelector& server_selector, - const std::string& subnet_prefix) { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_BY_PREFIX_SUBNET6) - .arg(subnet_prefix); - uint64_t result = impl_->deleteSubnet6(server_selector, subnet_prefix); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_BY_PREFIX_SUBNET6_RESULT) - .arg(result); - return (result); -} - -uint64_t -PgSqlConfigBackendDHCPv6::deleteSubnet6(const ServerSelector& server_selector, - const SubnetID& subnet_id) { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_BY_SUBNET_ID_SUBNET6) - .arg(subnet_id); - uint64_t result = impl_->deleteSubnet6(server_selector, subnet_id); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_BY_SUBNET_ID_SUBNET6_RESULT) - .arg(result); - return (result); -} - -uint64_t -PgSqlConfigBackendDHCPv6::deleteAllSubnets6(const ServerSelector& server_selector) { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_ALL_SUBNETS6); - - int index = (server_selector.amUnassigned() ? - PgSqlConfigBackendDHCPv6Impl::DELETE_ALL_SUBNETS6_UNASSIGNED : - PgSqlConfigBackendDHCPv6Impl::DELETE_ALL_SUBNETS6); - uint64_t result = impl_->deleteTransactional(index, server_selector, "deleting all subnets", - "deleted all subnets", true); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_ALL_SUBNETS6_RESULT).arg(result); - return (result); -} - -uint64_t -PgSqlConfigBackendDHCPv6::deleteSharedNetworkSubnets6(const db::ServerSelector& server_selector, - const std::string& shared_network_name) { - if (!server_selector.amAny()) { - isc_throw(InvalidOperation, "deleting all subnets from a shared " - "network requires using ANY server selector"); - } - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_SHARED_NETWORK_SUBNETS6) - .arg(shared_network_name); - uint64_t result = impl_->deleteTransactional( - PgSqlConfigBackendDHCPv6Impl::DELETE_ALL_SUBNETS6_SHARED_NETWORK_NAME, server_selector, - "deleting all subnets for a shared network", "deleted all subnets for a shared network", - true, shared_network_name); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_SHARED_NETWORK_SUBNETS6_RESULT) - .arg(result); - return (result); -} - -uint64_t -PgSqlConfigBackendDHCPv6::deleteSharedNetwork6(const ServerSelector& server_selector, - const std::string& name) { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_SHARED_NETWORK6).arg(name); - int index = (server_selector.amAny() ? - PgSqlConfigBackendDHCPv6Impl::DELETE_SHARED_NETWORK6_NAME_ANY : - PgSqlConfigBackendDHCPv6Impl::DELETE_SHARED_NETWORK6_NAME_WITH_TAG); - uint64_t result = impl_->deleteTransactional(index, server_selector, - "deleting a shared network", - "shared network deleted", true, name); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_SHARED_NETWORK6_RESULT) - .arg(result); - return (result); -} - -uint64_t -PgSqlConfigBackendDHCPv6::deleteAllSharedNetworks6(const ServerSelector& server_selector) { - if (server_selector.amAny()) { - isc_throw(InvalidOperation, "deleting all shared networks for ANY server is not" - " supported"); - } - - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_ALL_SHARED_NETWORKS6); - - int index = (server_selector.amUnassigned() ? - PgSqlConfigBackendDHCPv6Impl::DELETE_ALL_SHARED_NETWORKS6_UNASSIGNED : - PgSqlConfigBackendDHCPv6Impl::DELETE_ALL_SHARED_NETWORKS6); - uint64_t result = impl_->deleteTransactional(index, server_selector, - "deleting all shared networks", - "deleted all shared networks", true); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_ALL_SHARED_NETWORKS6_RESULT) - .arg(result); - return (result); -} - -uint64_t -PgSqlConfigBackendDHCPv6::deleteOptionDef6(const ServerSelector& server_selector, - const uint16_t code, - const std::string& space) { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_OPTION_DEF6).arg(code).arg(space); - uint64_t result = impl_->deleteOptionDef6(server_selector, code, space); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_OPTION_DEF6_RESULT).arg(result); - return (result); -} - -uint64_t -PgSqlConfigBackendDHCPv6::deleteAllOptionDefs6(const ServerSelector& server_selector) { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_ALL_OPTION_DEFS6); - uint64_t result = - impl_->deleteTransactional(PgSqlConfigBackendDHCPv6Impl::DELETE_ALL_OPTION_DEFS6, - server_selector, "deleting all option definitions", - "deleted all option definitions", true); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_ALL_OPTION_DEFS6_RESULT) - .arg(result); - return (result); -} - -uint64_t -PgSqlConfigBackendDHCPv6::deleteOption6(const ServerSelector& server_selector, - const uint16_t code, - const std::string& space) { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_OPTION6).arg(code).arg(space); - uint64_t result = impl_->deleteOption6(server_selector, code, space); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_OPTION6_RESULT).arg(result); - return (result); -} - -uint64_t -PgSqlConfigBackendDHCPv6::deleteOption6(const ServerSelector& /* server_selector */, - const std::string& shared_network_name, - const uint16_t code, - const std::string& space) { - /// @todo In the future we might use the server selector to make sure that the - /// option is only deleted if the pool belongs to a given server. For now, we - /// just delete it when there is a match with the parent object. - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_SHARED_NETWORK_OPTION6) - .arg(shared_network_name) - .arg(code) - .arg(space); - uint64_t result = impl_->deleteOption6(ServerSelector::ANY(), shared_network_name, code, space); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_SHARED_NETWORK_OPTION6_RESULT) - .arg(result); - return (result); -} - -uint64_t -PgSqlConfigBackendDHCPv6::deleteOption6(const ServerSelector& /* server_selector */, - const SubnetID& subnet_id, - const uint16_t code, - const std::string& space) { - /// @todo In the future we might use the server selector to make sure that the - /// option is only deleted if the pool belongs to a given server. For now, we - /// just delete it when there is a match with the parent object. - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_BY_SUBNET_ID_OPTION6) - .arg(subnet_id) - .arg(code) - .arg(space); - uint64_t result = impl_->deleteOption6(ServerSelector::ANY(), subnet_id, code, space); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_BY_SUBNET_ID_OPTION6_RESULT) - .arg(result); - return (result); -} - -uint64_t -PgSqlConfigBackendDHCPv6::deleteOption6(const ServerSelector& /* server_selector */, - const asiolink::IOAddress& pool_start_address, - const asiolink::IOAddress& pool_end_address, - const uint16_t code, - const std::string& space) { - /// @todo In the future we might use the server selector to make sure that the - /// option is only deleted if the pool belongs to a given server. For now, we - /// just delete it when there is a match with the parent object. - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_BY_POOL_OPTION6) - .arg(pool_start_address.toText()) - .arg(pool_end_address.toText()) - .arg(code) - .arg(space); - uint64_t result = impl_->deleteOption6(ServerSelector::ANY(), pool_start_address, - pool_end_address, code, space); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_BY_POOL_OPTION6_RESULT) - .arg(result); - return (result); -} - -uint64_t -PgSqlConfigBackendDHCPv6::deleteOption6(const ServerSelector& /* server_selector */, - const asiolink::IOAddress& pd_pool_prefix, - const uint8_t pd_pool_prefix_length, - const uint16_t code, - const std::string& space) { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_BY_POOL_PREFIX_OPTION6) - .arg(pd_pool_prefix.toText()) - .arg(pd_pool_prefix_length) - .arg(code) - .arg(space); - uint64_t result = impl_->deleteOption6(ServerSelector::ANY(), pd_pool_prefix, - pd_pool_prefix_length, code, space); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_BY_POOL_PREFIX_OPTION6_RESULT) - .arg(result); - return (result); -} - -uint64_t -PgSqlConfigBackendDHCPv6::deleteGlobalParameter6(const ServerSelector& server_selector, - const std::string& name) { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_GLOBAL_PARAMETER6).arg(name); - uint64_t result = - impl_->deleteTransactional(PgSqlConfigBackendDHCPv6Impl::DELETE_GLOBAL_PARAMETER6, - server_selector, "deleting global parameter", - "global parameter deleted", false, name); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_GLOBAL_PARAMETER6_RESULT) - .arg(result); - return (result); -} - -uint64_t -PgSqlConfigBackendDHCPv6::deleteAllGlobalParameters6(const ServerSelector& server_selector) { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_ALL_GLOBAL_PARAMETERS6); - uint64_t result = - impl_->deleteTransactional(PgSqlConfigBackendDHCPv6Impl::DELETE_ALL_GLOBAL_PARAMETERS6, - server_selector, "deleting all global parameters", - "all global parameters deleted", true); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_ALL_GLOBAL_PARAMETERS6_RESULT) - .arg(result); - return (result); -} - -uint64_t -PgSqlConfigBackendDHCPv6::deleteServer6(const ServerTag& server_tag) { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_SERVER6).arg(server_tag.get()); - uint64_t result = impl_->deleteServer6(server_tag); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_SERVER6_RESULT).arg(result); - return (result); -} - -uint64_t -PgSqlConfigBackendDHCPv6::deleteAllServers6() { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_ALL_SERVERS6); - uint64_t result = impl_->deleteAllServers6(); - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_DELETE_ALL_SERVERS6_RESULT).arg(result); - return (result); -} - -std::string -PgSqlConfigBackendDHCPv6::getType() const { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_TYPE6); - return (impl_->getType()); -} - -std::string -PgSqlConfigBackendDHCPv6::getHost() const { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_HOST6); - return (impl_->getHost()); -} - -uint16_t -PgSqlConfigBackendDHCPv6::getPort() const { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_GET_PORT6); - return (impl_->getPort()); -} - -bool -PgSqlConfigBackendDHCPv6::registerBackendType() { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_REGISTER_BACKEND_TYPE6); - return (dhcp::ConfigBackendDHCPv6Mgr::instance().registerBackendFactory( - "pgsql", - [](const db::DatabaseConnection::ParameterMap& params) -> dhcp::ConfigBackendDHCPv6Ptr { - return (dhcp::PgSqlConfigBackendDHCPv6Ptr(new dhcp::PgSqlConfigBackendDHCPv6(params))); - })); -} - -void -PgSqlConfigBackendDHCPv6::unregisterBackendType() { - LOG_DEBUG(pgsql_cb_logger, DBGLVL_TRACE_BASIC, PGSQL_CB_UNREGISTER_BACKEND_TYPE6); - dhcp::ConfigBackendDHCPv6Mgr::instance().unregisterBackendFactory("pgsql"); -} - -void -PgSqlConfigBackendDHCPv6::createUpdateClientClass6(const db::ServerSelector& server_selector, - const ClientClassDefPtr& client_class, - const std::string& follow_class_name) { - isc_throw(NotImplemented, "Not implemented yet."); -} - -ClientClassDefPtr -PgSqlConfigBackendDHCPv6::getClientClass6(const db::ServerSelector& selector, - const std::string& name) const { - isc_throw(NotImplemented, "Not implemented yet."); -} - -ClientClassDictionary -PgSqlConfigBackendDHCPv6::getAllClientClasses6(const db::ServerSelector& selector) const { - isc_throw(NotImplemented, "Not implemented yet."); -} - -ClientClassDictionary -PgSqlConfigBackendDHCPv6::getModifiedClientClasses6( - const db::ServerSelector& selector, const boost::posix_time::ptime& modification_time) const { - isc_throw(NotImplemented, "Not implemented yet."); -} - -uint64_t -PgSqlConfigBackendDHCPv6::deleteClientClass6(const db::ServerSelector& server_selector, - const std::string& name) { - isc_throw(NotImplemented, "Not implemented yet."); -} - -uint64_t -PgSqlConfigBackendDHCPv6::deleteAllClientClasses6(const db::ServerSelector& server_selector) { - isc_throw(NotImplemented, "Not implemented yet."); -} - -} // namespace dhcp -} // end of namespace isc diff --git a/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp6.h b/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp6.h deleted file mode 100644 index 44660a06e8..0000000000 --- a/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp6.h +++ /dev/null @@ -1,622 +0,0 @@ -// Copyright (C) 2021 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 PGSQL_CONFIG_BACKEND_DHCP6_H -#define PGSQL_CONFIG_BACKEND_DHCP6_H - -#include -#include - -#include - -#include -#include - -namespace isc { -namespace dhcp { - -class PgSqlConfigBackendDHCPv6Impl; - -/// @brief Implementation of the Postgres Configuration Backend for -/// Kea DHCPv6 server. -/// -/// All POSIX times specified in the methods belonging to this -/// class must be local times. -/// -/// The server selection mechanisms used by this backend generally adhere -/// to the rules described for @c ConfigBackendDHCPv6, but support for -/// some of the selectors is not implemented. Whenever this is the case, -/// the methods throw @c isc::NotImplemented exception. -class PgSqlConfigBackendDHCPv6 : public ConfigBackendDHCPv6 { -public: - /// @brief Constructor. - /// - /// @param parameters A data structure relating keywords and values - /// concerned with the database. - explicit PgSqlConfigBackendDHCPv6(const db::DatabaseConnection::ParameterMap& parameters); - - /// @brief Retrieves a single subnet by subnet_prefix. - /// - /// @param server_selector Server selector. - /// @param subnet_prefix Prefix of the subnet to be retrieved. - /// @return Pointer to the retrieved subnet or NULL if not found. - virtual Subnet6Ptr - getSubnet6(const db::ServerSelector& server_selector, const std::string& subnet_prefix) const; - - /// @brief Retrieves a single subnet by subnet identifier. - /// - /// @param server_selector Server selector. - /// @param subnet_id Identifier of a subnet to be retrieved. - /// @return Pointer to the retrieved subnet or NULL if not found. - virtual Subnet6Ptr - getSubnet6(const db::ServerSelector& server_selector, const SubnetID& subnet_id) const; - - /// @brief Retrieves all subnets. - /// - /// @param server_selector Server selector. - /// @return Collection of subnets or empty collection if no subnet found. - virtual Subnet6Collection getAllSubnets6(const db::ServerSelector& server_selector) const; - - /// @brief Retrieves subnets modified after specified time. - /// - /// @param server_selector Server selector. - /// @param modification_time Lower bound subnet modification time. - /// @return Collection of subnets or empty collection if no subnet found. - virtual Subnet6Collection - getModifiedSubnets6(const db::ServerSelector& server_selector, - const boost::posix_time::ptime& modification_time) const; - - /// @brief Retrieves all subnets belonging to a specified shared network. - /// - /// The server selector is currently ignored by this method. All subnets - /// for the given shared network are returned regardless of their - /// associations with the servers. - /// - /// @param server_selector Server selector (currently ignored). - /// @param shared_network_name Name of the shared network for which the - /// subnets should be retrieved. - /// @return Collection of subnets or empty collection if no subnet found. - virtual Subnet6Collection - getSharedNetworkSubnets6(const db::ServerSelector& server_selector, - const std::string& shared_network_name) const; - - /// @brief Retrieves shared network by name. - /// - /// @param server_selector Server selector. - /// @param name Name of the shared network to be retrieved. - /// @return Pointer to the shared network or NULL if not found. - /// @throw NotImplemented if server selector is "unassigned". - virtual SharedNetwork6Ptr - getSharedNetwork6(const db::ServerSelector& server_selector, const std::string& name) const; - - /// @brief Retrieves all shared networks. - /// - /// @param server_selector Server selector. - /// @return Collection of shared network or empty collection if - /// no shared network found. - virtual SharedNetwork6Collection - getAllSharedNetworks6(const db::ServerSelector& server_selector) const; - - /// @brief Retrieves shared networks modified after specified time. - /// - /// @param server_selector Server selector. - /// @param modification_time Lower bound shared network modification time. - /// @return Collection of shared network or empty collection if - /// no shared network found. - virtual SharedNetwork6Collection - getModifiedSharedNetworks6(const db::ServerSelector& server_selector, - const boost::posix_time::ptime& modification_time) const; - - /// @brief Retrieves single option definition by code and space. - /// - /// @param server_selector Server selector. - /// @param code Code of the option to be retrieved. - /// @param space Option space of the option to be retrieved. - /// @return Pointer to the option definition or NULL if not found. - /// @throw NotImplemented if server selector is "unassigned". - virtual OptionDefinitionPtr getOptionDef6(const db::ServerSelector& server_selector, - const uint16_t code, - const std::string& space) const; - - /// @brief Retrieves all option definitions. - /// - /// @param server_selector Server selector. - /// @return Collection of option definitions or empty collection if - /// no option definition found. - virtual OptionDefContainer getAllOptionDefs6(const db::ServerSelector& server_selector) const; - - /// @brief Retrieves option definitions modified after specified time. - /// - /// @param server_selector Server selector. - /// @param modification_time Lower bound option definition modification - /// time. - /// @return Collection of option definitions or empty collection if - /// no option definition found. - virtual OptionDefContainer - getModifiedOptionDefs6(const db::ServerSelector& server_selector, - const boost::posix_time::ptime& modification_time) const; - - /// @brief Retrieves single option by code and space. - /// - /// @param server_selector Server selector. - /// @return Pointer to the retrieved option descriptor or null if - /// no option was found. - /// @throw NotImplemented if server selector is "unassigned". - virtual OptionDescriptorPtr getOption6(const db::ServerSelector& server_selector, - const uint16_t code, - const std::string& space) const; - - /// @brief Retrieves all global options. - /// - /// @param server_selector Server selector. - /// @return Collection of global options or empty collection if no - /// option found. - virtual OptionContainer getAllOptions6(const db::ServerSelector& server_selector) const; - - /// @brief Retrieves option modified after specified time. - /// - /// @param server_selector Server selector. - /// @param modification_time Lower bound option modification time. - /// @return Collection of global options or empty collection if no - /// option found. - virtual OptionContainer - getModifiedOptions6(const db::ServerSelector& server_selector, - const boost::posix_time::ptime& modification_time) const; - - /// @brief Retrieves global parameter value. - /// - /// Typically, the server selector used for this query should be set to - /// ONE. It is possible to use the MULTIPLE server selector but in that - /// case only the first found parameter is returned. - /// - /// @param server_selector Server selector. - /// @param name Name of the global parameter to be retrieved. - /// @return Value of the global parameter. - /// @throw NotImplemented if server selector is "unassigned". - virtual data::StampedValuePtr - getGlobalParameter6(const db::ServerSelector& server_selector, const std::string& name) const; - - /// @brief Retrieves all global parameters. - /// - /// Using the server selector it is possible to fetch the parameters for - /// one or more servers. The following list describes what parameters are - /// returned depending on the server selector specified: - /// - ALL: only common parameters are returned which are associated with - /// the logical server 'all'. No parameters associated with the explicit - /// server tags are returned. - /// - /// - ONE: parameters used by the particular sever are returned. This includes - /// parameters associated with the particular server (identified by tag) - /// and parameters associated with the logical server 'all' when server - /// specific parameters are not given. For example, if there is a - /// renew-timer specified for 'server1' tag, different value of the - /// renew-timer specified for 'all' servers and a rebind-timer specified - /// for 'all' servers, the caller will receive renew-timer value associated - /// with the server1 and the rebind-timer value associated with all servers, - /// because there is no explicit rebind-timer specified for server1. - /// - /// - MULTIPLE: parameters used by multiple servers, but those associated - /// with specific server tags take precedence over the values specified for - /// 'all' servers. This is similar to the case of ONE server described - /// above. The effect of querying for parameters belonging to multiple - /// servers is the same as issuing multiple queries with ONE server - /// being selected multiple times. - /// - /// - UNASSIGNED: parameters not associated with any servers. - /// - /// - /// @param server_selector Server selector. - virtual data::StampedValueCollection - getAllGlobalParameters6(const db::ServerSelector& server_selector) const; - - /// @brief Retrieves global parameters modified after specified time. - /// - /// @param modification_time Lower bound modification time. - /// @return Collection of modified global parameters. - virtual data::StampedValueCollection - getModifiedGlobalParameters6(const db::ServerSelector& server_selector, - const boost::posix_time::ptime& modification_time) const; - - /// @brief Retrieves a client class by name. - /// - /// @param selector Server selector. - /// @param name Client class name. - /// @return Pointer to the retrieved client class. - virtual ClientClassDefPtr - getClientClass6(const db::ServerSelector& selector, const std::string& name) const; - - /// @brief Retrieves all client classes. - /// - /// @param selector Server selector. - /// @return Collection of client classes. - virtual ClientClassDictionary getAllClientClasses6(const db::ServerSelector& selector) const; - - /// @brief Retrieves client classes modified after specified time. - /// - /// @param selector Server selector. - /// @param modification_time Modification time. - /// @return Collection of client classes. - virtual ClientClassDictionary - getModifiedClientClasses6(const db::ServerSelector& selector, - const boost::posix_time::ptime& modification_time) const; - - /// @brief Retrieves the most recent audit entries. - /// - /// @param selector Server selector. - /// @param modification_time Timestamp being a lower limit for the returned - /// result set, i.e. entries later than specified time are returned. - /// @param modification_id Identifier being a lower limit for the returned - /// result set, used when two (or more) entries have the same - /// modification_time. - /// @return Collection of audit entries. - virtual db::AuditEntryCollection - getRecentAuditEntries(const db::ServerSelector& server_selector, - const boost::posix_time::ptime& modification_time, - const uint64_t& modification_id) const; - - /// @brief Retrieves all servers. - /// - /// This method returns the list of servers excluding the logical server - /// 'all'. - /// - /// @return Collection of servers from the backend. - virtual db::ServerCollection getAllServers6() const; - - /// @brief Retrieves a server. - /// - /// @param server_tag Tag of the server to be retrieved. - /// @return Pointer to the server instance or null pointer if no server - /// with the particular tag was found. - virtual db::ServerPtr getServer6(const data::ServerTag& server_tag) const; - - /// @brief Creates or updates a subnet. - /// - /// @param server_selector Server selector. - /// @param subnet Subnet to be added or updated. - /// @throw NotImplemented if server selector is "unassigned". - virtual void - createUpdateSubnet6(const db::ServerSelector& server_selector, const Subnet6Ptr& subnet); - - /// @brief Creates or updates a shared network. - /// - /// @param server_selector Server selector. - /// @param shared_network Shared network to be added or updated. - /// @throw NotImplemented if server selector is "unassigned". - virtual void createUpdateSharedNetwork6(const db::ServerSelector& server_selector, - const SharedNetwork6Ptr& shared_network); - - /// @brief Creates or updates an option definition. - /// - /// @param server_selector Server selector. - /// @param option_def Option definition to be added or updated. - /// @throw NotImplemented if server selector is "unassigned". - virtual void createUpdateOptionDef6(const db::ServerSelector& server_selector, - const OptionDefinitionPtr& option_def); - - /// @brief Creates or updates global option. - /// - /// @param server_selector Server selector. - /// @param option Option to be added or updated. - /// @throw NotImplemented if server selector is "unassigned". - virtual void createUpdateOption6(const db::ServerSelector& server_selector, - const OptionDescriptorPtr& option); - - /// @brief Creates or updates shared network level option. - /// - /// @param server_selector Server selector. - /// @param shared_network_name Name of a shared network to which option - /// belongs. - /// @param option Option to be added or updated. - /// @throw NotImplemented if server selector is "unassigned". - virtual void createUpdateOption6(const db::ServerSelector& server_selector, - const std::string& shared_network_name, - const OptionDescriptorPtr& option); - - /// @brief Creates or updates subnet level option. - /// - /// @param server_selector Server selector. - /// @param subnet_id Identifier of a subnet to which option belongs. - /// @param option Option to be added or updated. - /// @throw NotImplemented if server selector is "unassigned". - virtual void createUpdateOption6(const db::ServerSelector& server_selector, - const SubnetID& subnet_id, - const OptionDescriptorPtr& option); - - /// @brief Creates or updates pool level option. - /// - /// @param server_selector Server selector. - /// @param pool_start_address Lower bound address of the pool to which - /// the option belongs. - /// @param pool_end_address Upper bound address of the pool to which the - /// option belongs. - /// @param option Option to be added or updated. - /// @throw NotImplemented if server selector is "unassigned". - virtual void createUpdateOption6(const db::ServerSelector& server_selector, - const asiolink::IOAddress& pool_start_address, - const asiolink::IOAddress& pool_end_address, - const OptionDescriptorPtr& option); - - /// @brief Creates or updates prefix delegation pool level option. - /// - /// @param server_selector Server selector. - /// @param pd_pool_prefix Address part of the prefix of the prefix - /// delegation pool to which the option belongs. - /// @param pd_pool_prefix_length Prefix length of the prefix - /// delegation pool to which the option belongs. - /// @param option Option to be added or updated. - /// @throw NotImplemented if server selector is "unassigned". - virtual void createUpdateOption6(const db::ServerSelector& server_selector, - const asiolink::IOAddress& pd_pool_prefix, - const uint8_t pd_pool_prefix_length, - const OptionDescriptorPtr& option); - - /// @brief Creates or updates global parameter. - /// - /// @param server_selector Server selector. - /// @param name Name of the global parameter. - /// @param value Value of the global parameter. - /// @throw NotImplemented if server selector is "unassigned". - virtual void createUpdateGlobalParameter6(const db::ServerSelector& server_selector, - const data::StampedValuePtr& value); - - /// @brief Creates or updates a client class. - /// - /// @param server_selector Server selector. - /// @param client_class Client class to be added or updated. - /// @param follow_class_name name of the class after which the - /// new or updated class should be positioned. An empty value - /// causes the class to be appended at the end of the class - /// hierarchy. - virtual void createUpdateClientClass6(const db::ServerSelector& server_selector, - const ClientClassDefPtr& client_class, - const std::string& follow_class_name); - - /// @brief Creates or updates a server. - /// - /// @param server Instance of the server to be stored. - /// @throw InvalidOperation when trying to create a duplicate or - /// update the logical server 'all'. - virtual void createUpdateServer6(const db::ServerPtr& server); - - /// @brief Deletes subnet by prefix. - /// - /// @param server_selector Server selector. - /// @param subnet_prefix Prefix of the subnet to be deleted. - /// @return Number of deleted subnets. - /// @throw NotImplemented if server selector is "unassigned". - virtual uint64_t - deleteSubnet6(const db::ServerSelector& server_selector, const std::string& subnet_prefix); - - /// @brief Deletes subnet by identifier. - /// - /// @param server_selector Server selector. - /// @param subnet_id Identifier of the subnet to be deleted. - /// @return Number of deleted subnets. - /// @throw NotImplemented if server selector is "unassigned". - virtual uint64_t - deleteSubnet6(const db::ServerSelector& server_selector, const SubnetID& subnet_id); - - /// @brief Deletes all subnets. - /// - /// @param server_selector Server selector. - /// @return Number of deleted subnets. - /// @throw NotImplemented if server selector is "unassigned". - virtual uint64_t deleteAllSubnets6(const db::ServerSelector& server_selector); - - /// @brief Deletes all subnets belonging to a specified shared network. - /// - /// @param server_selector Server selector. - /// @param shared_network_name Name of the shared network for which the - /// subnets should be deleted. - /// @return Number of deleted subnets. - virtual uint64_t deleteSharedNetworkSubnets6(const db::ServerSelector& server_selector, - const std::string& shared_network_name); - - /// @brief Deletes shared network by name. - /// - /// @param server_selector Server selector. - /// @param name Name of the shared network to be deleted. - /// @return Number of deleted shared networks. - /// @throw NotImplemented if server selector is "unassigned". - virtual uint64_t - deleteSharedNetwork6(const db::ServerSelector& server_selector, const std::string& name); - - /// @brief Deletes all shared networks. - /// - /// @param server_selector Server selector. - /// @return Number of deleted shared networks. - virtual uint64_t deleteAllSharedNetworks6(const db::ServerSelector& server_selector); - - /// @brief Deletes option definition. - /// - /// @param server_selector Server selector. - /// @param code Code of the option to be deleted. - /// @param space Option space of the option to be deleted. - /// @return Number of deleted option definitions. - /// @throw NotImplemented if server selector is "unassigned". - virtual uint64_t deleteOptionDef6(const db::ServerSelector& server_selector, - const uint16_t code, - const std::string& space); - - /// @brief Deletes all option definitions. - /// - /// @param server_selector Server selector. - /// @return Number of deleted option definitions. - /// @throw NotImplemented if server selector is "unassigned". - virtual uint64_t deleteAllOptionDefs6(const db::ServerSelector& server_selector); - - /// @brief Deletes global option. - /// - /// @param server_selector Server selector. - /// @param code Code of the option to be deleted. - /// @param space Option space of the option to be deleted. - /// @return Number of deleted options. - /// @throw NotImplemented if server selector is "unassigned". - virtual uint64_t deleteOption6(const db::ServerSelector& server_selector, - const uint16_t code, - const std::string& space); - - /// @brief Deletes shared network level option. - /// - /// @param server_selector Server selector. - /// @param shared_network_name Name of the shared network which deleted - /// option belongs to - /// @param code Code of the deleted option. - /// @param space Option space of the deleted option. - /// @throw NotImplemented if server selector is "unassigned". - virtual uint64_t deleteOption6(const db::ServerSelector& server_selector, - const std::string& shared_network_name, - const uint16_t code, - const std::string& space); - - /// @brief Deletes subnet level option. - /// - /// @param server_selector Server selector. - /// @param subnet_id Identifier of the subnet to which deleted option - /// belongs. - /// @param code Code of the deleted option. - /// @param space Option space of the deleted option. - /// @return Number of deleted options. - /// @throw NotImplemented if server selector is "unassigned". - virtual uint64_t deleteOption6(const db::ServerSelector& server_selector, - const SubnetID& subnet_id, - const uint16_t code, - const std::string& space); - - /// @brief Deletes pool level option. - /// - /// @param server_selector Server selector. - /// @param pool_start_address Lower bound address of the pool to which - /// deleted option belongs. - /// @param pool_end_address Upper bound address of the pool to which the - /// deleted option belongs. - /// @param code Code of the deleted option. - /// @param space Option space of the deleted option. - /// @return Number of deleted options. - /// @throw NotImplemented if server selector is "unassigned". - virtual uint64_t deleteOption6(const db::ServerSelector& server_selector, - const asiolink::IOAddress& pool_start_address, - const asiolink::IOAddress& pool_end_address, - const uint16_t code, - const std::string& space); - - /// @brief Deletes prefix delegation pool level option. - /// - /// @param server_selector Server selector. - /// @param pool_start_address Lower bound address of the prefix - /// delegation pool to which deleted option belongs. - /// @param pool_end_address Upper bound address of the prefix - /// delegation pool to which the deleted option belongs. - /// @param code Code of the deleted option. - /// @param space Option space of the deleted option. - /// @return Number of deleted options. - /// @throw NotImplemented if server selector is "unassigned". - virtual uint64_t deleteOption6(const db::ServerSelector& server_selector, - const asiolink::IOAddress& pd_pool_prefix, - const uint8_t pd_pool_prefix_length, - const uint16_t code, - const std::string& space); - - /// @brief Deletes global parameter. - /// - /// @param server_selector Server selector. - /// @param name Name of the global parameter to be deleted. - /// @return Number of deleted global parameters. - /// @throw NotImplemented if server selector is "unassigned". - virtual uint64_t - deleteGlobalParameter6(const db::ServerSelector& server_selector, const std::string& name); - - /// @brief Deletes all global parameters. - /// - /// @param server_selector Server selector. - /// @return Number of deleted global parameters. - /// @throw NotImplemented if server selector is "unassigned". - virtual uint64_t deleteAllGlobalParameters6(const db::ServerSelector& server_selector); - - /// @brief Deletes a client class. - /// - /// @param server_selector Server selector. - /// @param name Name of the class to be deleted. - /// @return Number of deleted client classes. - virtual uint64_t - deleteClientClass6(const db::ServerSelector& server_selector, const std::string& name); - - /// @brief Deletes all client classes. - /// - /// @param server_selector Server selector. - /// @return Number of deleted client classes. - virtual uint64_t deleteAllClientClasses6(const db::ServerSelector& server_selector); - - /// @brief Deletes a server from the backend. - /// - /// @param server_tag Tag of the server to be deleted. - /// @return Number of deleted servers. - /// @throw isc::InvalidOperation when trying to delete the logical - /// server 'all'. - virtual uint64_t deleteServer6(const data::ServerTag& server_tag); - - /// @brief Deletes all servers from the backend except the logical - /// server 'all'. - /// - /// @return Number of deleted servers. - virtual uint64_t deleteAllServers6(); - - /// @brief Returns backend type in the textual format. - /// - /// @return "pgsql". - virtual std::string getType() const; - - /// @brief Returns backend host. - /// - /// This is used by the @c BaseConfigBackendPool to select backend - /// when @c BackendSelector is specified. - /// - /// @return host on which the database is located. - virtual std::string getHost() const; - - /// @brief Returns backend port number. - /// - /// This is used by the @c BaseConfigBackendPool to select backend - /// when @c BackendSelector is specified. - /// - /// @return Port number on which database service is available. - virtual uint16_t getPort() const; - - /// @brief Registers the Postgres backend factory with backend config manager - /// - /// This should be called by the hook lib load() function. - /// @return True if the factory was registered successfully, false otherwise. - static bool registerBackendType(); - - /// @brief Unregisters the Postgres backend factory and discards Postgres backends - /// - /// This should be called by the hook lib unload() function. - static void unregisterBackendType(); - - /// @brief Flag which indicates if the config backend has an unusable - /// connection. - /// - /// @return true if there is at least one unusable connection, false - /// otherwise - virtual bool isUnusable(); - -protected: - /// @brief Pointer to the implementation of the @c PgSqlConfigBackendDHCPv6 - /// class. - boost::shared_ptr impl_; - - /// @brief Pointer to the base implementation of the backend shared by - /// DHCPv4 and DHCPv6 servers. - boost::shared_ptr base_impl_; -}; - -/// @brief Pointer to the @c PgSqlConfigBackendDHCPv6 class. -typedef boost::shared_ptr PgSqlConfigBackendDHCPv6Ptr; - -} // namespace dhcp -} // end of namespace isc - -#endif // PGSQL_CONFIG_BACKEND_DHCP6_H diff --git a/src/hooks/dhcp/pgsql_cb/tests/pgsql_cb_dhcp6_mgr_unittest.cc b/src/hooks/dhcp/pgsql_cb/tests/pgsql_cb_dhcp6_mgr_unittest.cc deleted file mode 100644 index 565dab12a2..0000000000 --- a/src/hooks/dhcp/pgsql_cb/tests/pgsql_cb_dhcp6_mgr_unittest.cc +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (C) 2021 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 -#include - -using namespace isc::data; -using namespace isc::dhcp; -using namespace isc::dhcp::test; -using namespace isc::db; -using namespace isc::db::test; - -namespace { - -/// @brief Test fixture class for @c PgSqlConfigBackendDHCPv6Mgr. -class PgSqlConfigBackendDHCPv6MgrTest : public GenericBackendTest { -public: - /// @brief Constructor. - PgSqlConfigBackendDHCPv6MgrTest() { - // Recreate a fresh mgr. - ConfigBackendDHCPv6Mgr::create(); - - // Ensure we have the proper schema with no transient data. - createPgSQLSchema(); - } - - /// @brief Destructor. - virtual ~PgSqlConfigBackendDHCPv6MgrTest() { - // Destroy the mgr. - ConfigBackendDHCPv6Mgr::destroy(); - - // If data wipe enabled, delete transient data otherwise destroy the schema. - destroyPgSQLSchema(); - } -}; - -// This test verifies that Postgres backend can be registered with and -// unregistered from the Config Backend Manager. -TEST_F(PgSqlConfigBackendDHCPv6MgrTest, factoryRegistration) { - - // Get the mgr singleton. - ConfigBackendDHCPv6Mgr& mgr = ConfigBackendDHCPv6Mgr::instance(); - - // With no factory registered, attempting to add a Postgres db should fail. - ASSERT_THROW(mgr.addBackend(validPgSQLConnectionString()), InvalidType); - - // Now we'll register the Postgres factory. - ASSERT_NO_THROW(PgSqlConfigBackendDHCPv6::registerBackendType()); - - // With the factory registered, attempting to add a Postgres db should succeed. - ASSERT_NO_THROW(mgr.addBackend(validPgSQLConnectionString())); - - // Create a Postgres backend selector for convenience. - BackendSelector pgsql(BackendSelector::Type::PGSQL); - - // Should be able to create a global parameter. - StampedValuePtr server_tag = StampedValue::create("server-tag", "whale"); - ASSERT_NO_THROW( - mgr.getPool()->createUpdateGlobalParameter6(pgsql, ServerSelector::ALL(), server_tag)); - // Verify parameter can be fetched. - server_tag.reset(); - ASSERT_NO_THROW(server_tag = mgr.getPool()->getGlobalParameter6(pgsql, ServerSelector::ALL(), - "server-tag")); - ASSERT_TRUE(server_tag); - EXPECT_EQ("server-tag", server_tag->getName()); - EXPECT_EQ("whale", server_tag->getValue()); - - // Now we'll unregister PgSQL. - ASSERT_NO_THROW(PgSqlConfigBackendDHCPv6::unregisterBackendType()); - - // With no factory registered, attempting to add a Postgres db should fail. - ASSERT_THROW(mgr.addBackend(validPgSQLConnectionString()), InvalidType); - - // Attempting to read the global parameter should fail. - ASSERT_THROW(mgr.getPool()->getGlobalParameter6(pgsql, ServerSelector::ALL(), "server-tag"), - NoSuchDatabase); -} - -} // namespace diff --git a/src/hooks/dhcp/pgsql_cb/tests/pgsql_cb_dhcp6_unittest.cc b/src/hooks/dhcp/pgsql_cb/tests/pgsql_cb_dhcp6_unittest.cc deleted file mode 100644 index 3d36c589e9..0000000000 --- a/src/hooks/dhcp/pgsql_cb/tests/pgsql_cb_dhcp6_unittest.cc +++ /dev/null @@ -1,4462 +0,0 @@ -// Copyright (C) 2021 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -using namespace isc; -using namespace isc::asiolink; -using namespace isc::db; -using namespace isc::db::test; -using namespace isc::data; -using namespace isc::dhcp; -using namespace isc::dhcp::test; -using namespace isc::process; -using namespace isc::test; -namespace ph = std::placeholders; - -namespace { - -/// @brief Test implementation of the Postgres configuration backend. -/// -/// It exposes protected members of the @c PgSqlConfigBackendDHCPv6. -class TestPgSqlConfigBackendDHCPv6 : public PgSqlConfigBackendDHCPv6 { -public: - /// @brief Constructor. - /// - /// @param parameters A data structure relating keywords and values - /// concerned with the database. - explicit TestPgSqlConfigBackendDHCPv6(const DatabaseConnection::ParameterMap& parameters) - : PgSqlConfigBackendDHCPv6(parameters) { - } - - using PgSqlConfigBackendDHCPv6::base_impl_; -}; - -/// @brief Test fixture class for @c PgSqlConfigBackendDHCPv6. -/// -/// @todo The tests we're providing here only test cases when the -/// server selector is set to 'ALL' (configuration elements belong to -/// all servers). Currently we have no API to insert servers into -/// the database, and therefore we can't test the case when -/// configuration elements are assigned to particular servers by -/// server tags. We will have to expand existing tests when -/// the API is extended allowing for inserting servers to the -/// database. -class PgSqlConfigBackendDHCPv6Test : public PgSqlGenericBackendTest { -public: - /// @brief Constructor. - PgSqlConfigBackendDHCPv6Test() - : test_subnets_(), test_networks_(), test_option_defs_(), test_options_(), test_servers_(), - timestamps_(), cbptr_(), audit_entries_() { - // Ensure we have the proper schema with no transient data. - createPgSQLSchema(); - - try { - // Create Postgres connection and use it to start the backend. - DatabaseConnection::ParameterMap params = - DatabaseConnection::parse(validPgSQLConnectionString()); - cbptr_.reset(new TestPgSqlConfigBackendDHCPv6(params)); - - } catch (...) { - std::cerr << "*** ERROR: unable to open database. The test\n" - "*** environment is broken and must be fixed before\n" - "*** the Postgres tests will run correctly.\n" - "*** The reason for the problem is described in the\n" - "*** accompanying exception output.\n"; - throw; - } - - // Create test data. - initTestServers(); - initTestOptions(); - initTestSubnets(); - initTestSharedNetworks(); - initTestOptionDefs(); - initTimestamps(); - } - - /// @brief Destructor. - virtual ~PgSqlConfigBackendDHCPv6Test() { - cbptr_.reset(); - // If data wipe enabled, delete transient data otherwise destroy the schema. - destroyPgSQLSchema(); - } - - /// @brief Counts rows in a selected table in Postgres database. - /// - /// This method can be used to verify that some configuration elements were - /// deleted from a selected table as a result of cascade delete or a trigger. - /// For example, deleting a subnet should trigger deletion of its address - /// pools and options. By counting the rows on each table we can determine - /// whether the deletion took place on all tables for which it was expected. - /// - /// @param table Table name. - /// @return Number of rows in the specified table. - size_t countRows(const std::string& table) const { - auto p = boost::dynamic_pointer_cast(cbptr_); - if (!p) { - ADD_FAILURE() << "cbptr_ does not cast to TestPgSqlConfigBackendDHCPv6"; - return (0); - } - - // Reuse the existing connection of the backend. - auto impl = boost::dynamic_pointer_cast(p->base_impl_); - auto& conn = impl->conn_; - - return (PgSqlGenericBackendTest::countRows(conn, table)); - } - - /// @brief Creates several servers used in tests. - void initTestServers() { - test_servers_.push_back(Server::create(ServerTag("server1"), "this is server 1")); - test_servers_.push_back(Server::create(ServerTag("server1"), "this is server 1 bis")); - test_servers_.push_back(Server::create(ServerTag("server2"), "this is server 2")); - test_servers_.push_back(Server::create(ServerTag("server3"), "this is server 3")); - } - - /// @brief Creates several subnets used in tests. - void initTestSubnets() { - // First subnet includes all parameters. - std::string interface_id_text = "whale"; - OptionBuffer interface_id(interface_id_text.begin(), interface_id_text.end()); - OptionPtr opt_interface_id(new Option(Option::V6, D6O_INTERFACE_ID, interface_id)); - ElementPtr user_context = Element::createMap(); - user_context->set("foo", Element::create("bar")); - - Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8::"), 64, 30, 40, 50, 60, 1024)); - subnet->allowClientClass("home"); - subnet->setIface("eth1"); - subnet->setInterfaceId(opt_interface_id); - subnet->setT2(323212); - subnet->addRelayAddress(IOAddress("2001:db8:1::2")); - subnet->addRelayAddress(IOAddress("2001:db8:3::4")); - subnet->setT1(1234); - subnet->requireClientClass("required-class1"); - subnet->requireClientClass("required-class2"); - subnet->setReservationsGlobal(false); - subnet->setReservationsInSubnet(false); - subnet->setContext(user_context); - subnet->setValid(555555); - subnet->setPreferred(4444444); - subnet->setCalculateTeeTimes(true); - subnet->setT1Percent(0.345); - subnet->setT2Percent(0.444); - subnet->setDdnsSendUpdates(false); - - Pool6Ptr pool1( - new Pool6(Lease::TYPE_NA, IOAddress("2001:db8::10"), IOAddress("2001:db8::20"))); - subnet->addPool(pool1); - - Pool6Ptr pool2( - new Pool6(Lease::TYPE_NA, IOAddress("2001:db8::50"), IOAddress("2001:db8::60"))); - subnet->addPool(pool2); - - Pool6Ptr pdpool1(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:a::"), 48, 64)); - subnet->addPool(pdpool1); - - Pool6Ptr pdpool2(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:b::"), 48, 64)); - subnet->addPool(pdpool2); - - // Add several options to the subnet. - subnet->getCfgOption()->add(test_options_[0]->option_, test_options_[0]->persistent_, - test_options_[0]->space_name_); - - subnet->getCfgOption()->add(test_options_[1]->option_, test_options_[1]->persistent_, - test_options_[1]->space_name_); - - subnet->getCfgOption()->add(test_options_[2]->option_, test_options_[2]->persistent_, - test_options_[2]->space_name_); - - test_subnets_.push_back(subnet); - - // Adding another subnet with the same subnet id to test - // cases that this second instance can override existing - // subnet instance. - subnet.reset(new Subnet6(IOAddress("2001:db8:1::"), 48, 20, 30, 40, 50, 1024)); - - pool1.reset( - new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1::10"), IOAddress("2001:db8:1::20"))); - subnet->addPool(pool1); - - pool1->getCfgOption()->add(test_options_[3]->option_, test_options_[3]->persistent_, - test_options_[3]->space_name_); - - pool1->getCfgOption()->add(test_options_[4]->option_, test_options_[4]->persistent_, - test_options_[4]->space_name_); - - pool2.reset( - new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1::50"), IOAddress("2001:db8:1::60"))); - subnet->addPool(pool2); - - pool2->allowClientClass("work"); - pool2->requireClientClass("required-class3"); - pool2->requireClientClass("required-class4"); - user_context = Element::createMap(); - user_context->set("bar", Element::create("foo")); - pool2->setContext(user_context); - - pdpool1.reset(new Pool6(IOAddress("2001:db8:c::"), 48, 64, IOAddress("2001:db8:c::1"), 96)); - subnet->addPool(pdpool1); - - pdpool1->getCfgOption()->add(test_options_[3]->option_, test_options_[3]->persistent_, - test_options_[3]->space_name_); - - pdpool1->getCfgOption()->add(test_options_[4]->option_, test_options_[4]->persistent_, - test_options_[4]->space_name_); - - // Create the prefix delegation pool with an excluded prefix. - pdpool2.reset( - new Pool6(IOAddress("2001:db8:d::"), 48, 64, IOAddress("2001:db8:d::2000"), 120)); - - subnet->addPool(pdpool2); - - pdpool2->allowClientClass("work"); - pdpool2->requireClientClass("required-class3"); - pdpool2->requireClientClass("required-class4"); - user_context = Element::createMap(); - user_context->set("bar", Element::create("foo")); - pdpool2->setContext(user_context); - - test_subnets_.push_back(subnet); - - subnet.reset(new Subnet6(IOAddress("2001:db8:3::"), 64, 20, 30, 40, 50, 2048)); - Triplet null_timer; - subnet->setPreferred(null_timer); - subnet->setT1(null_timer); - subnet->setT2(null_timer); - subnet->setValid(null_timer); - subnet->setPreferred(null_timer); - subnet->setDdnsSendUpdates(true); - subnet->setDdnsOverrideNoUpdate(true); - subnet->setDdnsOverrideClientUpdate(false); - subnet->setDdnsReplaceClientNameMode( - D2ClientConfig::ReplaceClientNameMode::RCM_WHEN_PRESENT); - subnet->setDdnsGeneratedPrefix("myhost"); - subnet->setDdnsQualifyingSuffix("example.org"); - - subnet->getCfgOption()->add(test_options_[0]->option_, test_options_[0]->persistent_, - test_options_[0]->space_name_); - - test_subnets_.push_back(subnet); - - // Add a subnet with all defaults. - subnet.reset(new Subnet6(IOAddress("2001:db8:4::"), 64, Triplet(), - Triplet(), Triplet(), Triplet(), - 4096)); - test_subnets_.push_back(subnet); - } - - /// @brief Creates several subnets used in tests. - void initTestSharedNetworks() { - ElementPtr user_context = Element::createMap(); - user_context->set("foo", Element::create("bar")); - - std::string interface_id_text = "fish"; - OptionBuffer interface_id(interface_id_text.begin(), interface_id_text.end()); - OptionPtr opt_interface_id(new Option(Option::V6, D6O_INTERFACE_ID, interface_id)); - - SharedNetwork6Ptr shared_network(new SharedNetwork6("level1")); - shared_network->allowClientClass("foo"); - shared_network->setIface("eth1"); - shared_network->setInterfaceId(opt_interface_id); - shared_network->setT2(323212); - shared_network->addRelayAddress(IOAddress("2001:db8:1::2")); - shared_network->addRelayAddress(IOAddress("2001:db8:3::4")); - shared_network->setT1(1234); - shared_network->requireClientClass("required-class1"); - shared_network->requireClientClass("required-class2"); - shared_network->setReservationsGlobal(false); - shared_network->setReservationsInSubnet(false); - shared_network->setContext(user_context); - shared_network->setValid(5555); - shared_network->setPreferred(4444); - shared_network->setCalculateTeeTimes(true); - shared_network->setT1Percent(0.345); - shared_network->setT2Percent(0.444); - shared_network->setDdnsSendUpdates(false); - - // Add several options to the shared network. - shared_network->getCfgOption()->add(test_options_[2]->option_, - test_options_[2]->persistent_, - test_options_[2]->space_name_); - - shared_network->getCfgOption()->add(test_options_[3]->option_, - test_options_[3]->persistent_, - test_options_[3]->space_name_); - - shared_network->getCfgOption()->add(test_options_[4]->option_, - test_options_[4]->persistent_, - test_options_[4]->space_name_); - - test_networks_.push_back(shared_network); - - // Adding another shared network called "level1" to test - // cases that this second instance can override existing - // "level1" instance. - shared_network.reset(new SharedNetwork6("level1")); - test_networks_.push_back(shared_network); - - // Add more shared networks. - shared_network.reset(new SharedNetwork6("level2")); - Triplet null_timer; - shared_network->setPreferred(null_timer); - shared_network->setT1(null_timer); - shared_network->setT2(null_timer); - shared_network->setValid(null_timer); - shared_network->setPreferred(null_timer); - shared_network->setDdnsSendUpdates(true); - shared_network->setDdnsOverrideNoUpdate(true); - shared_network->setDdnsOverrideClientUpdate(false); - shared_network->setDdnsReplaceClientNameMode( - D2ClientConfig::ReplaceClientNameMode::RCM_WHEN_PRESENT); - shared_network->setDdnsGeneratedPrefix("myhost"); - shared_network->setDdnsQualifyingSuffix("example.org"); - - shared_network->getCfgOption()->add(test_options_[0]->option_, - test_options_[0]->persistent_, - test_options_[0]->space_name_); - test_networks_.push_back(shared_network); - - shared_network.reset(new SharedNetwork6("level3")); - test_networks_.push_back(shared_network); - } - - /// @brief Creates several option definitions used in tests. - void initTestOptionDefs() { - ElementPtr user_context = Element::createMap(); - user_context->set("foo", Element::create("bar")); - - OptionDefinitionPtr option_def( - new OptionDefinition("foo", 1234, DHCP6_OPTION_SPACE, "string", "espace")); - test_option_defs_.push_back(option_def); - - option_def.reset(new OptionDefinition("bar", 1234, DHCP6_OPTION_SPACE, "uint32", true)); - test_option_defs_.push_back(option_def); - - option_def.reset(new OptionDefinition("fish", 5235, DHCP6_OPTION_SPACE, "record", true)); - option_def->addRecordField("uint32"); - option_def->addRecordField("string"); - test_option_defs_.push_back(option_def); - - option_def.reset(new OptionDefinition("whale", 20236, "xyz", "string")); - test_option_defs_.push_back(option_def); - - option_def.reset(new OptionDefinition("bar", 1234, DHCP6_OPTION_SPACE, "uint64", true)); - test_option_defs_.push_back(option_def); - } - - /// @brief Creates several DHCP options used in tests. - void initTestOptions() { - ElementPtr user_context = Element::createMap(); - user_context->set("foo", Element::create("bar")); - - OptionDefSpaceContainer defs; - - OptionDescriptor desc = createOption(Option::V6, D6O_NEW_POSIX_TIMEZONE, true, - false, "my-timezone"); - desc.space_name_ = DHCP6_OPTION_SPACE; - desc.setContext(user_context); - test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc))); - - desc = createOption(Option::V6, D6O_PREFERENCE, false, true, 64); - desc.space_name_ = DHCP6_OPTION_SPACE; - test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc))); - - desc = createOption(Option::V6, 1, false, false, 312131), - desc.space_name_ = "vendor-encapsulated-options"; - test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc))); - - desc = createAddressOption(1254, true, true, "2001:db8::3"); - desc.space_name_ = DHCP6_OPTION_SPACE; - test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc))); - - desc = createEmptyOption(Option::V6, 1, true); - desc.space_name_ = "isc"; - test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc))); - - desc = createAddressOption(2, false, true, "2001:db8:1::5", "2001:db8:1::3", - "2001:db8:3::4"); - desc.space_name_ = "isc"; - test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc))); - - desc = createOption(Option::V6, D6O_NEW_POSIX_TIMEZONE, true, false, - "my-timezone-2"); - desc.space_name_ = DHCP6_OPTION_SPACE; - desc.setContext(user_context); - test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc))); - - desc = createOption(Option::V6, D6O_NEW_POSIX_TIMEZONE, true, false, - "my-timezone-3"); - desc.space_name_ = DHCP6_OPTION_SPACE; - desc.setContext(user_context); - test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc))); - - // Add definitions for DHCPv6 non-standard options in case we need to - // compare subnets, networks and pools in JSON format. In that case, - // the @c toElement functions require option definitions to generate the - // proper output. - defs.addItem( - OptionDefinitionPtr(new OptionDefinition("vendor-encapsulated-1", 1, - "vendor-encapsulated-options", "uint32"))); - defs.addItem(OptionDefinitionPtr( - new OptionDefinition("option-1254", 1254, DHCP6_OPTION_SPACE, "ipv6-address", true))); - defs.addItem(OptionDefinitionPtr(new OptionDefinition("isc-1", 1, "isc", "empty"))); - defs.addItem( - OptionDefinitionPtr(new OptionDefinition("isc-2", 2, "isc", "ipv6-address", true))); - - // Register option definitions. - LibDHCP::setRuntimeOptionDefs(defs); - } - - /// @brief Initialize posix time values used in tests. - void initTimestamps() { - // Current time minus 1 hour to make sure it is in the past. - timestamps_["today"] = boost::posix_time::second_clock::local_time() - - boost::posix_time::hours(1); - // One second after today. - timestamps_["after today"] = timestamps_["today"] + boost::posix_time::seconds(1); - // Yesterday. - timestamps_["yesterday"] = timestamps_["today"] - boost::posix_time::hours(24); - // One second after yesterday. - timestamps_["after yesterday"] = timestamps_["yesterday"] + boost::posix_time::seconds(1); - // Two days ago. - timestamps_["two days ago"] = timestamps_["today"] - boost::posix_time::hours(48); - // Tomorrow. - timestamps_["tomorrow"] = timestamps_["today"] + boost::posix_time::hours(24); - // One second after tomorrow. - timestamps_["after tomorrow"] = timestamps_["tomorrow"] + boost::posix_time::seconds(1); - } - - /// @brief Logs audit entries in the @c audit_entries_ member. - /// - /// This function is called in case of an error. - /// - /// @param server_tag Server tag for which the audit entries should be logged. - std::string logExistingAuditEntries(const std::string& server_tag) { - std::ostringstream s; - - auto& mod_time_idx = audit_entries_[server_tag].get(); - - for (auto audit_entry_it = mod_time_idx.begin(); audit_entry_it != mod_time_idx.end(); - ++audit_entry_it) { - auto audit_entry = *audit_entry_it; - s << audit_entry->getObjectType() << ", " << audit_entry->getObjectId() << ", " - << static_cast(audit_entry->getModificationType()) << ", " - << audit_entry->getModificationTime() << ", " << audit_entry->getRevisionId() << ", " - << audit_entry->getLogMessage() << std::endl; - } - - return (s.str()); - } - - /// @brief Tests that the new audit entry is added. - /// - /// This method retrieves a collection of the existing audit entries and - /// checks that the new one has been added at the end of this collection. - /// It then verifies the values of the audit entry against the values - /// specified by the caller. - /// - /// @param exp_object_type Expected object type. - /// @param exp_modification_type Expected modification type. - /// @param exp_log_message Expected log message. - /// @param server_selector Server selector to be used for next query. - /// @param new_entries_num Number of the new entries expected to be inserted. - /// @param max_tested_entries Maximum number of entries tested. - void testNewAuditEntry(const std::string& exp_object_type, - const AuditEntry::ModificationType& exp_modification_type, - const std::string& exp_log_message, - const ServerSelector& server_selector = ServerSelector::ALL(), - const size_t new_entries_num = 1, - const size_t max_tested_entries = 65535) { - // Get the server tag for which the entries are fetched. - std::string tag; - if (server_selector.getType() == ServerSelector::Type::ALL) { - // Server tag is 'all'. - tag = "all"; - - } else { - auto tags = server_selector.getTags(); - // This test is not meant to handle multiple server tags all at once. - if (tags.size() > 1) { - ADD_FAILURE() << "Test error: do not use multiple server tags"; - - } else if (tags.size() == 1) { - // Get the server tag for which we run the current test. - tag = tags.begin()->get(); - } - } - - auto audit_entries_size_save = audit_entries_[tag].size(); - - // Audit entries for different server tags are stored in separate - // containers. - audit_entries_[tag] = cbptr_->getRecentAuditEntries(server_selector, - timestamps_["two days ago"], 0); - ASSERT_EQ(audit_entries_size_save + new_entries_num, audit_entries_[tag].size()) - << logExistingAuditEntries(tag); - - auto& mod_time_idx = audit_entries_[tag].get(); - - // Iterate over specified number of entries starting from the most recent - // one and check they have correct values. - for (auto audit_entry_it = mod_time_idx.rbegin(); - ((std::distance(mod_time_idx.rbegin(), audit_entry_it) < new_entries_num) && - (std::distance(mod_time_idx.rbegin(), audit_entry_it) < max_tested_entries)); - ++audit_entry_it) { - auto audit_entry = *audit_entry_it; - EXPECT_EQ(exp_object_type, audit_entry->getObjectType()) - << logExistingAuditEntries(tag); - EXPECT_EQ(exp_modification_type, audit_entry->getModificationType()) - << logExistingAuditEntries(tag); - EXPECT_EQ(exp_log_message, audit_entry->getLogMessage()) - << logExistingAuditEntries(tag); - } - } - - /// @brief Holds pointers to subnets used in tests. - std::vector test_subnets_; - - /// @brief Holds pointers to shared networks used in tests. - std::vector test_networks_; - - /// @brief Holds pointers to option definitions used in tests. - std::vector test_option_defs_; - - /// @brief Holds pointers to options used in tests. - std::vector test_options_; - - /// @brief Holds pointers to the servers used in tests. - std::vector test_servers_; - - /// @brief Holds timestamp values used in tests. - std::map timestamps_; - - /// @brief Holds pointer to the backend. - boost::shared_ptr cbptr_; - - /// @brief Holds the most recent audit entries. - std::map audit_entries_; -}; - -// This test verifies that the expected backend type is returned. -TEST_F(PgSqlConfigBackendDHCPv6Test, getType) { - DatabaseConnection::ParameterMap params; - params["name"] = "keatest"; - params["password"] = "keatest"; - params["user"] = "keatest"; - ASSERT_NO_THROW(cbptr_.reset(new PgSqlConfigBackendDHCPv6(params))); - EXPECT_EQ("pgsql", cbptr_->getType()); -} - -// This test verifies that by default localhost is returned as Postgres connection -// host. -TEST_F(PgSqlConfigBackendDHCPv6Test, getHost) { - DatabaseConnection::ParameterMap params; - params["name"] = "keatest"; - params["password"] = "keatest"; - params["user"] = "keatest"; - ASSERT_NO_THROW(cbptr_.reset(new PgSqlConfigBackendDHCPv6(params))); - EXPECT_EQ("localhost", cbptr_->getHost()); -} - -// This test verifies that by default port of 0 is returned as Postgres connection -// port. -TEST_F(PgSqlConfigBackendDHCPv6Test, getPort) { - DatabaseConnection::ParameterMap params; - params["name"] = "keatest"; - params["password"] = "keatest"; - params["user"] = "keatest"; - ASSERT_NO_THROW(cbptr_.reset(new PgSqlConfigBackendDHCPv6(params))); - EXPECT_EQ(0, cbptr_->getPort()); -} - -// This test verifies that the server can be added, updated and deleted. -TEST_F(PgSqlConfigBackendDHCPv6Test, createUpdateDeleteServer) { - // Explicitly set modification time to make sure that the time - // returned from the database is correct. - test_servers_[0]->setModificationTime(timestamps_["yesterday"]); - test_servers_[1]->setModificationTime(timestamps_["today"]); - - // Insert the server1 into the database. - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[0])); - - { - SCOPED_TRACE("CREATE audit entry for server"); - testNewAuditEntry("dhcp6_server", AuditEntry::ModificationType::CREATE, "server set"); - } - - // It should not be possible to create a duplicate of the logical - // server 'all'. - auto all_server = Server::create(ServerTag("all"), "this is logical server all"); - EXPECT_THROW(cbptr_->createUpdateServer6(all_server), isc::InvalidOperation); - - ServerPtr returned_server; - - // An attempt to fetch the server that hasn't been inserted should return - // a null pointer. - EXPECT_NO_THROW(returned_server = cbptr_->getServer6(ServerTag("server2"))); - EXPECT_FALSE(returned_server); - - // Try to fetch the server which we expect to exist. - EXPECT_NO_THROW(returned_server = cbptr_->getServer6(ServerTag("server1"))); - ASSERT_TRUE(returned_server); - EXPECT_EQ("server1", returned_server->getServerTagAsText()); - EXPECT_EQ("this is server 1", returned_server->getDescription()); - EXPECT_EQ(timestamps_["yesterday"], returned_server->getModificationTime()); - - // This call is expected to update the existing server. - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[1])); - - { - SCOPED_TRACE("UPDATE audit entry for server"); - testNewAuditEntry("dhcp6_server", AuditEntry::ModificationType::UPDATE, "server set"); - } - - // Verify that the server has been updated. - EXPECT_NO_THROW(returned_server = cbptr_->getServer6(ServerTag("server1"))); - ASSERT_TRUE(returned_server); - EXPECT_EQ("server1", returned_server->getServerTag().get()); - EXPECT_EQ("this is server 1 bis", returned_server->getDescription()); - EXPECT_EQ(timestamps_["today"], returned_server->getModificationTime()); - - uint64_t servers_deleted = 0; - - // Try to delete non-existing server. - EXPECT_NO_THROW(servers_deleted = cbptr_->deleteServer6(ServerTag("server2"))); - EXPECT_EQ(0, servers_deleted); - - // Make sure that the server1 wasn't deleted. - EXPECT_NO_THROW(returned_server = cbptr_->getServer6(ServerTag("server1"))); - EXPECT_TRUE(returned_server); - - // Deleting logical server 'all' is not allowed. - EXPECT_THROW(cbptr_->deleteServer6(ServerTag()), isc::InvalidOperation); - - // Delete the existing server. - EXPECT_NO_THROW(servers_deleted = cbptr_->deleteServer6(ServerTag("server1"))); - EXPECT_EQ(1, servers_deleted); - - { - SCOPED_TRACE("DELETE audit entry for server"); - testNewAuditEntry("dhcp6_server", AuditEntry::ModificationType::DELETE, - "deleting a server"); - } - - // Make sure that the server is gone. - EXPECT_NO_THROW(returned_server = cbptr_->getServer6(ServerTag("server1"))); - EXPECT_FALSE(returned_server); -} - -// This test verifies that it is possible to retrieve all servers from the -// database and then delete all of them. -TEST_F(PgSqlConfigBackendDHCPv6Test, getAndDeleteAllServers) { - for (auto i = 1; i < test_servers_.size(); ++i) { - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[i])); - } - - ServerCollection servers; - EXPECT_NO_THROW(servers = cbptr_->getAllServers6()); - ASSERT_EQ(test_servers_.size() - 1, servers.size()); - - // All servers should have been returned. - EXPECT_TRUE(ServerFetcher::get(servers, ServerTag("server1"))); - EXPECT_TRUE(ServerFetcher::get(servers, ServerTag("server2"))); - EXPECT_TRUE(ServerFetcher::get(servers, ServerTag("server3"))); - - // The logical server all should not be returned. We merely return the - // user configured servers. - EXPECT_FALSE(ServerFetcher::get(servers, ServerTag())); - - // Delete all servers and make sure they are gone. - uint64_t deleted_servers = 0; - EXPECT_NO_THROW(deleted_servers = cbptr_->deleteAllServers6()); - - EXPECT_NO_THROW(servers = cbptr_->getAllServers6()); - EXPECT_TRUE(servers.empty()); - - // All servers should be gone. - EXPECT_FALSE(ServerFetcher::get(servers, ServerTag("server1"))); - EXPECT_FALSE(ServerFetcher::get(servers, ServerTag("server2"))); - EXPECT_FALSE(ServerFetcher::get(servers, ServerTag("server3"))); - - // The number of deleted server should be equal to the number of - // inserted servers. The logical 'all' server should be excluded. - EXPECT_EQ(test_servers_.size() - 1, deleted_servers); -} - -// This test verifies that the global parameter can be added, updated and -// deleted. -TEST_F(PgSqlConfigBackendDHCPv6Test, createUpdateDeleteGlobalParameter6) { - StampedValuePtr global_parameter = StampedValue::create("global", "whale"); - - // Explicitly set modification time to make sure that the time - // returned from the database is correct. - global_parameter->setModificationTime(timestamps_["yesterday"]); - cbptr_->createUpdateGlobalParameter6(ServerSelector::ALL(), global_parameter); - - { - SCOPED_TRACE("CREATE audit entry for global parameter"); - testNewAuditEntry("dhcp6_global_parameter", AuditEntry::ModificationType::CREATE, - "global parameter set"); - } - - // Verify returned parameter and the modification time. - StampedValuePtr returned_global_parameter = cbptr_->getGlobalParameter6(ServerSelector::ALL(), - "global"); - ASSERT_TRUE(returned_global_parameter); - EXPECT_EQ("global", returned_global_parameter->getName()); - EXPECT_EQ("whale", returned_global_parameter->getValue()); - EXPECT_TRUE(returned_global_parameter->getModificationTime() == - global_parameter->getModificationTime()); - ASSERT_EQ(1, returned_global_parameter->getServerTags().size()); - EXPECT_EQ("all", returned_global_parameter->getServerTags().begin()->get()); - - // Because we have added the global parameter for all servers, it - // should be also returned for the explicitly specified server. - returned_global_parameter = cbptr_->getGlobalParameter6(ServerSelector::ONE("server1"), - "global"); - ASSERT_TRUE(returned_global_parameter); - EXPECT_EQ("global", returned_global_parameter->getName()); - EXPECT_EQ("whale", returned_global_parameter->getValue()); - EXPECT_TRUE(returned_global_parameter->getModificationTime() == - global_parameter->getModificationTime()); - ASSERT_EQ(1, returned_global_parameter->getServerTags().size()); - EXPECT_EQ("all", returned_global_parameter->getServerTags().begin()->get()); - - // Check that the parameter is updated when selector is specified correctly. - global_parameter = StampedValue::create("global", "fish"); - cbptr_->createUpdateGlobalParameter6(ServerSelector::ALL(), global_parameter); - returned_global_parameter = cbptr_->getGlobalParameter6(ServerSelector::ALL(), "global"); - ASSERT_TRUE(returned_global_parameter); - EXPECT_EQ("global", returned_global_parameter->getName()); - EXPECT_EQ("fish", returned_global_parameter->getValue()); - EXPECT_TRUE(returned_global_parameter->getModificationTime() == - global_parameter->getModificationTime()); - - { - SCOPED_TRACE("UPDATE audit entry for the global parameter"); - testNewAuditEntry("dhcp6_global_parameter", AuditEntry::ModificationType::UPDATE, - "global parameter set"); - } - - // Should not delete parameter specified for all servers if explicit - // server name is provided. - EXPECT_EQ(0, cbptr_->deleteGlobalParameter6(ServerSelector::ONE("server1"), "global")); - - // Delete parameter and make sure it is gone. - cbptr_->deleteGlobalParameter6(ServerSelector::ALL(), "global"); - returned_global_parameter = cbptr_->getGlobalParameter6(ServerSelector::ALL(), "global"); - EXPECT_FALSE(returned_global_parameter); - - { - SCOPED_TRACE("DELETE audit entry for the global parameter"); - testNewAuditEntry("dhcp6_global_parameter", AuditEntry::ModificationType::DELETE, - "global parameter deleted"); - } -} - -// This test verifies that it is possible to differentiate between the -// global parameters by server tag and that the value specified for the -// particular server overrides the value specified for all servers. -TEST_F(PgSqlConfigBackendDHCPv6Test, globalParameters6WithServerTags) { - // Create three global parameters having the same name. - StampedValuePtr global_parameter1 = StampedValue::create("global", "value1"); - StampedValuePtr global_parameter2 = StampedValue::create("global", "value2"); - StampedValuePtr global_parameter3 = StampedValue::create("global", "value3"); - - // Try to insert one of them and associate with non-existing server. - // This should fail because the server must be inserted first. - EXPECT_THROW(cbptr_->createUpdateGlobalParameter6(ServerSelector::ONE("server1"), - global_parameter1), - NullKeyError); - - // Create two servers. - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[1])); - { - SCOPED_TRACE("server1 is created"); - testNewAuditEntry("dhcp6_server", AuditEntry::ModificationType::CREATE, "server set"); - } - - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[2])); - { - SCOPED_TRACE("server2 is created"); - testNewAuditEntry("dhcp6_server", AuditEntry::ModificationType::CREATE, "server set"); - } - - // This time inserting the global parameters for the server1 and server2 should - // be successful. - EXPECT_NO_THROW( - cbptr_->createUpdateGlobalParameter6(ServerSelector::ONE("server1"), global_parameter1)); - { - SCOPED_TRACE("Global parameter for server1 is set"); - // The value of 3 means there should be 3 audit entries available for the - // server1, two that indicate creation of the servers and one that we - // validate, which sets the global value. - testNewAuditEntry("dhcp6_global_parameter", AuditEntry::ModificationType::CREATE, - "global parameter set", ServerSelector::ONE("server1"), 3, 1); - } - - EXPECT_NO_THROW( - cbptr_->createUpdateGlobalParameter6(ServerSelector::ONE("server2"), global_parameter2)); - { - SCOPED_TRACE("Global parameter for server2 is set"); - // Same as in case of the server2, there should be 3 audit entries of - // which one we validate. - testNewAuditEntry("dhcp6_global_parameter", AuditEntry::ModificationType::CREATE, - "global parameter set", ServerSelector::ONE("server2"), 3, 1); - } - - // The last parameter is associated with all servers. - EXPECT_NO_THROW(cbptr_->createUpdateGlobalParameter6(ServerSelector::ALL(), global_parameter3)); - { - SCOPED_TRACE("Global parameter for all servers is set"); - // There should be one new audit entry for all servers. It indicates - // the insertion of the global value. - testNewAuditEntry("dhcp6_global_parameter", AuditEntry::ModificationType::CREATE, - "global parameter set", ServerSelector::ALL(), 1, 1); - } - - StampedValuePtr returned_global; - - // Try to fetch the value specified for all servers. - EXPECT_NO_THROW(returned_global = cbptr_->getGlobalParameter6(ServerSelector::ALL(), "global")); - ASSERT_TRUE(returned_global); - EXPECT_EQ(global_parameter3->getValue(), returned_global->getValue()); - ASSERT_EQ(1, returned_global->getServerTags().size()); - EXPECT_EQ("all", returned_global->getServerTags().begin()->get()); - - // Try to fetch the value specified for the server1. This should override the - // value specified for all servers. - EXPECT_NO_THROW( - returned_global = cbptr_->getGlobalParameter6(ServerSelector::ONE("server1"), "global")); - ASSERT_TRUE(returned_global); - EXPECT_EQ(global_parameter1->getValue(), returned_global->getValue()); - - ASSERT_EQ(1, returned_global->getServerTags().size()); - EXPECT_EQ("server1", returned_global->getServerTags().begin()->get()); - - // The same in case of the server2. - EXPECT_NO_THROW( - returned_global = cbptr_->getGlobalParameter6(ServerSelector::ONE("server2"), "global")); - ASSERT_TRUE(returned_global); - EXPECT_EQ(global_parameter2->getValue(), returned_global->getValue()); - ASSERT_EQ(1, returned_global->getServerTags().size()); - EXPECT_EQ("server2", returned_global->getServerTags().begin()->get()); - - StampedValueCollection returned_globals; - - // Try to fetch the collection of globals for the server1, server2 and server3. - // The server3 does not have an explicit value so for this server we should get - /// the value for 'all'. - EXPECT_NO_THROW(returned_globals = cbptr_->getAllGlobalParameters6( - ServerSelector::MULTIPLE({"server1", "server2", "server3"}));); - ASSERT_EQ(3, returned_globals.size()); - - // Capture the returned values into the map so as we can check the - // values against the servers. - std::map values; - for (auto g = returned_globals.begin(); g != returned_globals.end(); ++g) { - ASSERT_EQ(1, (*g)->getServerTags().size()); - values[(*g)->getServerTags().begin()->get()] = ((*g)->getValue()); - } - - ASSERT_EQ(3, values.size()); - EXPECT_EQ(global_parameter1->getValue(), values["server1"]); - EXPECT_EQ(global_parameter2->getValue(), values["server2"]); - EXPECT_EQ(global_parameter3->getValue(), values["all"]); - - // Try to fetch the collection of global parameters specified for all servers. - // This excludes the values specific to server1 and server2. It returns only the - // common ones. - EXPECT_NO_THROW(returned_globals = cbptr_->getAllGlobalParameters6(ServerSelector::ALL())); - ASSERT_EQ(1, returned_globals.size()); - returned_global = *returned_globals.begin(); - EXPECT_EQ(global_parameter3->getValue(), returned_global->getValue()); - ASSERT_EQ(1, returned_global->getServerTags().size()); - EXPECT_EQ("all", returned_global->getServerTags().begin()->get()); - - // Delete the server1. It should remove associations of this server with the - // global parameter and the global parameter itself. - EXPECT_NO_THROW(cbptr_->deleteServer6(ServerTag("server1"))); - EXPECT_NO_THROW( - returned_globals = cbptr_->getAllGlobalParameters6(ServerSelector::ONE("server1"))); - ASSERT_EQ(1, returned_globals.size()); - returned_global = *returned_globals.begin(); - // As a result, the value fetched for the server1 should be the one available for - // all servers, rather than the one dedicated for server1. The association of - // the server1 specific value with the server1 should be gone. - EXPECT_EQ(global_parameter3->getValue(), returned_global->getValue()); - ASSERT_EQ(1, returned_global->getServerTags().size()); - EXPECT_EQ("all", returned_global->getServerTags().begin()->get()); - - { - SCOPED_TRACE("DELETE audit entry for the global parameter after server deletion"); - // We expect two new audit entries for the server1, one indicating that the - // server has been deleted and another one indicating that the corresponding - // global value has been deleted. We check the latter entry. - testNewAuditEntry("dhcp6_global_parameter", AuditEntry::ModificationType::DELETE, - "deleting a server", ServerSelector::ONE("server1"), 2, 1); - } - - // Attempt to delete global parameter for server1. - uint64_t deleted_num = 0; - EXPECT_NO_THROW( - deleted_num = cbptr_->deleteGlobalParameter6(ServerSelector::ONE("server1"), "global")); - // No parameters should be deleted. In particular, the parameter for the logical - // server 'all' should not be deleted. - EXPECT_EQ(0, deleted_num); - - // Deleting the existing value for server2 should succeed. - EXPECT_NO_THROW( - deleted_num = cbptr_->deleteGlobalParameter6(ServerSelector::ONE("server2"), "global")); - EXPECT_EQ(1, deleted_num); - - // Create it again to test that deletion of all server removes this too. - EXPECT_NO_THROW( - cbptr_->createUpdateGlobalParameter6(ServerSelector::ONE("server2"), global_parameter2)); - - // Delete all servers, except 'all'. - EXPECT_NO_THROW(deleted_num = cbptr_->deleteAllServers6()); - EXPECT_NO_THROW(returned_globals = cbptr_->getAllGlobalParameters6(ServerSelector::ALL())); - EXPECT_EQ(1, deleted_num); - ASSERT_EQ(1, returned_globals.size()); - returned_global = *returned_globals.begin(); - // The common value for all servers should still be available because 'all' - // logical server should not be deleted. - EXPECT_EQ(global_parameter3->getValue(), returned_global->getValue()); - ASSERT_EQ(1, returned_global->getServerTags().size()); - EXPECT_EQ("all", returned_global->getServerTags().begin()->get()); - - { - SCOPED_TRACE("DELETE audit entry for the global parameter after deletion of" - " all servers"); - // There should be 4 new audit entries. One for deleting the global, one for - // re-creating it, one for deleting the server2 and one for deleting the - // global again as a result of deleting the server2. - testNewAuditEntry("dhcp6_global_parameter", AuditEntry::ModificationType::DELETE, - "deleting all servers", ServerSelector::ONE("server2"), 4, 1); - } -} - -// This test verifies that all global parameters can be retrieved and deleted. -TEST_F(PgSqlConfigBackendDHCPv6Test, getAllGlobalParameters6) { - // Create 3 parameters and put them into the database. - cbptr_->createUpdateGlobalParameter6(ServerSelector::ALL(), - StampedValue::create("name1", "value1")); - cbptr_->createUpdateGlobalParameter6( - ServerSelector::ALL(), - StampedValue::create("name2", Element::create(static_cast(65)))); - cbptr_->createUpdateGlobalParameter6(ServerSelector::ALL(), - StampedValue::create("name3", "value3")); - cbptr_->createUpdateGlobalParameter6( - ServerSelector::ALL(), - StampedValue::create("name4", Element::create(static_cast(true)))); - cbptr_->createUpdateGlobalParameter6( - ServerSelector::ALL(), - StampedValue::create("name5", Element::create(static_cast(1.65)))); - - // Fetch all parameters. - auto parameters = cbptr_->getAllGlobalParameters6(ServerSelector::ALL()); - ASSERT_EQ(5, parameters.size()); - - const auto& parameters_index = parameters.get(); - - for (auto param = parameters_index.begin(); param != parameters_index.end(); ++param) { - ASSERT_EQ(1, (*param)->getServerTags().size()); - EXPECT_EQ("all", (*param)->getServerTags().begin()->get()); - } - - // Verify their values. - EXPECT_EQ("value1", (*parameters_index.find("name1"))->getValue()); - EXPECT_EQ(65, (*parameters_index.find("name2"))->getIntegerValue()); - EXPECT_EQ("value3", (*parameters_index.find("name3"))->getValue()); - EXPECT_TRUE((*parameters_index.find("name4"))->getBoolValue()); - EXPECT_EQ(1.65, (*parameters_index.find("name5"))->getDoubleValue()); - - // Should be able to fetch these parameters when explicitly providing - // the server tag. - parameters = cbptr_->getAllGlobalParameters6(ServerSelector::ONE("server1")); - EXPECT_EQ(5, parameters.size()); - - // Deleting global parameters with non-matching server selector - // should fail. - EXPECT_EQ(0, cbptr_->deleteAllGlobalParameters6(ServerSelector::ONE("server1"))); - - // Delete all parameters and make sure they are gone. - EXPECT_EQ(5, cbptr_->deleteAllGlobalParameters6(ServerSelector::ALL())); - parameters = cbptr_->getAllGlobalParameters6(ServerSelector::ALL()); - EXPECT_TRUE(parameters.empty()); -} - -// This test verifies that modified global parameters can be retrieved. -TEST_F(PgSqlConfigBackendDHCPv6Test, getModifiedGlobalParameters6) { - // Create 3 global parameters and assign modification times: - // "yesterday", "today" and "tomorrow" respectively. - StampedValuePtr value = StampedValue::create("name1", "value1"); - value->setModificationTime(timestamps_["yesterday"]); - cbptr_->createUpdateGlobalParameter6(ServerSelector::ALL(), value); - - value = StampedValue::create("name2", Element::create(static_cast(65))); - value->setModificationTime(timestamps_["today"]); - cbptr_->createUpdateGlobalParameter6(ServerSelector::ALL(), value); - - value = StampedValue::create("name3", "value3"); - value->setModificationTime(timestamps_["tomorrow"]); - cbptr_->createUpdateGlobalParameter6(ServerSelector::ALL(), value); - - // Get parameters modified after "today". - auto parameters = cbptr_->getModifiedGlobalParameters6(ServerSelector::ALL(), - timestamps_["after today"]); - - const auto& parameters_index = parameters.get(); - - // It should be the one modified "tomorrow". - ASSERT_EQ(1, parameters_index.size()); - - auto parameter = parameters_index.find("name3"); - ASSERT_FALSE(parameter == parameters_index.end()); - - ASSERT_TRUE(*parameter); - EXPECT_EQ("value3", (*parameter)->getValue()); - - // Should be able to fetct these parameters when explicitly providing - // the server tag. - parameters = cbptr_->getModifiedGlobalParameters6(ServerSelector::ONE("server1"), - timestamps_["after today"]); - EXPECT_EQ(1, parameters.size()); -} - -// Test that the NullKeyError message is correctly updated. -TEST_F(PgSqlConfigBackendDHCPv6Test, nullKeyError) { - // Create a global parameter (it should work with any object type). - StampedValuePtr global_parameter = StampedValue::create("global", "value"); - - // Try to insert it and associate with non-existing server. - std::string msg; - try { - cbptr_->createUpdateGlobalParameter6(ServerSelector::ONE("server1"), global_parameter); - msg = "got no exception"; - } catch (const NullKeyError& ex) { - msg = ex.what(); - } catch (const std::exception&) { - msg = "got another exception"; - } - EXPECT_EQ("server 'server1' does not exist", msg); -} - -// Test that ceateUpdateSubnet6 throws appropriate exceptions for various -// server selectors. -TEST_F(PgSqlConfigBackendDHCPv6Test, createUpdateSubnet6Selectors) { - ASSERT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[0])); - ASSERT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[2])); - - // Supported selectors. - Subnet6Ptr subnet = test_subnets_[0]; - EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet)); - subnet = test_subnets_[2]; - EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ONE("server1"), subnet)); - subnet = test_subnets_[3]; - EXPECT_NO_THROW( - cbptr_->createUpdateSubnet6(ServerSelector::MULTIPLE({"server1", "server2"}), subnet)); - - // Not supported server selectors. - EXPECT_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ANY(), subnet), isc::InvalidOperation); - - // Not implemented server selectors. - EXPECT_THROW(cbptr_->createUpdateSubnet6(ServerSelector::UNASSIGNED(), subnet), - isc::NotImplemented); -} - -// Test that subnet can be inserted, fetched, updated and then fetched again. -TEST_F(PgSqlConfigBackendDHCPv6Test, getSubnet6) { - // Insert the server2 into the database. - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[2])); - { - SCOPED_TRACE("CREATE audit entry for server"); - testNewAuditEntry("dhcp6_server", AuditEntry::ModificationType::CREATE, "server set"); - } - - auto subnet = test_subnets_[0]; - auto subnet2 = test_subnets_[2]; - - // An attempt to add a subnet to a non-existing server (server1) should fail. - EXPECT_THROW(cbptr_->createUpdateSubnet6(ServerSelector::MULTIPLE({"server1", "server2"}), - subnet2), - NullKeyError); - - // The subnet shouldn't have been added, even though one of the servers exists. - Subnet6Ptr returned_subnet; - ASSERT_NO_THROW( - returned_subnet = cbptr_->getSubnet6(ServerSelector::ONE("server2"), subnet2->getID())); - EXPECT_FALSE(returned_subnet); - - // Insert two subnets, one for all servers and one for server2. - EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet)); - { - SCOPED_TRACE("CREATE audit entry for the subnet"); - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::CREATE, "subnet set"); - } - - EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ONE("server2"), subnet2)); - { - SCOPED_TRACE("CREATE audit entry for the subnet"); - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::CREATE, "subnet set", - ServerSelector::ONE("subnet2"), 2, 1); - } - - // We are not going to support selection of a single entry for multiple servers. - EXPECT_THROW(cbptr_->getSubnet6(ServerSelector::MULTIPLE({"server1", "server2"}), - subnet->getID()), - isc::InvalidOperation); - - EXPECT_THROW(cbptr_->getSubnet6(ServerSelector::MULTIPLE({"server1", "server2"}), - subnet->toText()), - isc::InvalidOperation); - - // Test that this subnet will be fetched for various server selectors. - auto test_get_subnet = [this, &subnet](const std::string& test_case_name, - const ServerSelector& server_selector, - const std::string& expected_tag = ServerTag::ALL) { - SCOPED_TRACE(test_case_name); - - // Test fetching subnet by id. - Subnet6Ptr returned_subnet; - ASSERT_NO_THROW(returned_subnet = cbptr_->getSubnet6(server_selector, subnet->getID())); - ASSERT_TRUE(returned_subnet); - - ASSERT_EQ(1, returned_subnet->getServerTags().size()); - EXPECT_TRUE(returned_subnet->hasServerTag(ServerTag(expected_tag))); - - EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str()); - - // Test fetching subnet by prefix. - ASSERT_NO_THROW(returned_subnet = cbptr_->getSubnet6(server_selector, subnet->toText())); - ASSERT_TRUE(returned_subnet); - - ASSERT_EQ(1, returned_subnet->getServerTags().size()); - EXPECT_TRUE(returned_subnet->hasServerTag(ServerTag(expected_tag))); - - EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str()); - }; - - { - SCOPED_TRACE("testing various server selectors before update"); - test_get_subnet("all servers", ServerSelector::ALL()); - test_get_subnet("one server", ServerSelector::ONE("server1")); - test_get_subnet("any server", ServerSelector::ANY()); - } - - subnet = subnet2; - { - SCOPED_TRACE("testing server selectors for another server"); - test_get_subnet("one server", ServerSelector::ONE("server2"), "server2"); - test_get_subnet("any server", ServerSelector::ANY(), "server2"); - } - - // Update the subnet in the database (both use the same ID). - subnet = test_subnets_[1]; - EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet)); - { - SCOPED_TRACE("CREATE audit entry for the subnet"); - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::UPDATE, "subnet set"); - } - - { - SCOPED_TRACE("testing various server selectors after update"); - test_get_subnet("all servers", ServerSelector::ALL()); - test_get_subnet("one server", ServerSelector::ONE("server1")); - test_get_subnet("any server", ServerSelector::ANY()); - } - - // The server2 specific subnet should not be returned if the server selector - // is not matching. - EXPECT_FALSE(cbptr_->getSubnet6(ServerSelector::ALL(), subnet2->getID())); - EXPECT_FALSE(cbptr_->getSubnet6(ServerSelector::ALL(), subnet2->toText())); - EXPECT_FALSE(cbptr_->getSubnet6(ServerSelector::ONE("server1"), subnet2->getID())); - EXPECT_FALSE(cbptr_->getSubnet6(ServerSelector::ONE("server1"), subnet2->toText())); - - // Update the subnet in the database (both use the same prefix). - subnet2.reset(new Subnet6(IOAddress("2001:db8:3::"), 64, 30, 40, 50, 80, 8192)); - EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ONE("server2"), subnet2)); - - // Fetch again and verify. - returned_subnet = cbptr_->getSubnet6(ServerSelector::ONE("server2"), subnet2->toText()); - ASSERT_TRUE(returned_subnet); - EXPECT_EQ(subnet2->toElement()->str(), returned_subnet->toElement()->str()); - - // Update the subnet when it conflicts same id and same prefix both - // with different subnets. This should throw. - // Subnets are 2001:db8:1::/48 id 1024 and 2001:db8:3::/64 id 8192 - subnet2.reset(new Subnet6(IOAddress("2001:db8:1::"), 48, 30, 40, 50, 80, 8192)); - EXPECT_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ONE("server2"), subnet2), - DuplicateEntry); -} - -// Test that getSubnet6 by ID throws appropriate exceptions for various server -// selectors. -TEST_F(PgSqlConfigBackendDHCPv6Test, getSubnet6byIdSelectors) { - // Supported selectors. - EXPECT_NO_THROW(cbptr_->getSubnet6(ServerSelector::ANY(), SubnetID(1))); - EXPECT_NO_THROW(cbptr_->getSubnet6(ServerSelector::UNASSIGNED(), SubnetID(1))); - EXPECT_NO_THROW(cbptr_->getSubnet6(ServerSelector::ALL(), SubnetID(1))); - EXPECT_NO_THROW(cbptr_->getSubnet6(ServerSelector::ONE("server1"), SubnetID(1))); - - // Not supported selectors. - EXPECT_THROW(cbptr_->getSubnet6(ServerSelector::MULTIPLE({"server1", "server2"}), SubnetID(1)), - isc::InvalidOperation); -} - -// Test that the information about unspecified optional parameters gets -// propagated to the database. -TEST_F(PgSqlConfigBackendDHCPv6Test, getSubnet6WithOptionalUnspecified) { - // Create a subnet and wrap it within a shared network. It is important - // to have the shared network to verify that the subnet doesn't inherit - // the values of the shared network but stores the NULL values in the - // for those parameters that are unspecified on the subnet level. - Subnet6Ptr subnet = test_subnets_[2]; - SharedNetwork6Ptr shared_network = test_networks_[0]; - shared_network->add(subnet); - - // Need to add the shared network to the database because otherwise - // the subnet foreign key would fail. - cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), shared_network); - cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet); - - // Fetch this subnet by subnet identifier. - Subnet6Ptr returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(), subnet->getID()); - ASSERT_TRUE(returned_subnet); - - EXPECT_TRUE(returned_subnet->getIface().unspecified()); - EXPECT_TRUE(returned_subnet->getIface().empty()); - - EXPECT_TRUE(returned_subnet->getClientClass().unspecified()); - EXPECT_TRUE(returned_subnet->getClientClass().empty()); - - EXPECT_TRUE(returned_subnet->getValid().unspecified()); - EXPECT_EQ(0, returned_subnet->getValid().get()); - - EXPECT_TRUE(returned_subnet->getPreferred().unspecified()); - EXPECT_EQ(0, returned_subnet->getPreferred().get()); - - EXPECT_TRUE(returned_subnet->getT1().unspecified()); - EXPECT_EQ(0, returned_subnet->getT1().get()); - - EXPECT_TRUE(returned_subnet->getT2().unspecified()); - EXPECT_EQ(0, returned_subnet->getT2().get()); - - EXPECT_TRUE(returned_subnet->getReservationsGlobal().unspecified()); - EXPECT_FALSE(returned_subnet->getReservationsGlobal().get()); - - EXPECT_TRUE(returned_subnet->getReservationsInSubnet().unspecified()); - EXPECT_TRUE(returned_subnet->getReservationsInSubnet().get()); - - EXPECT_TRUE(returned_subnet->getReservationsOutOfPool().unspecified()); - EXPECT_FALSE(returned_subnet->getReservationsOutOfPool().get()); - - EXPECT_TRUE(returned_subnet->getCalculateTeeTimes().unspecified()); - EXPECT_FALSE(returned_subnet->getCalculateTeeTimes().get()); - - EXPECT_TRUE(returned_subnet->getT1Percent().unspecified()); - EXPECT_EQ(0.0, returned_subnet->getT1Percent().get()); - - EXPECT_TRUE(returned_subnet->getT2Percent().unspecified()); - EXPECT_EQ(0.0, returned_subnet->getT2Percent().get()); - - EXPECT_TRUE(returned_subnet->getRapidCommit().unspecified()); - EXPECT_FALSE(returned_subnet->getRapidCommit().get()); - - EXPECT_FALSE(returned_subnet->getDdnsSendUpdates().unspecified()); - EXPECT_TRUE(returned_subnet->getDdnsSendUpdates().get()); - - EXPECT_FALSE(returned_subnet->getDdnsOverrideNoUpdate().unspecified()); - EXPECT_TRUE(returned_subnet->getDdnsOverrideNoUpdate().get()); - - EXPECT_FALSE(returned_subnet->getDdnsOverrideClientUpdate().unspecified()); - EXPECT_FALSE(returned_subnet->getDdnsOverrideClientUpdate().get()); - - EXPECT_FALSE(returned_subnet->getDdnsReplaceClientNameMode().unspecified()); - EXPECT_EQ(D2ClientConfig::ReplaceClientNameMode::RCM_WHEN_PRESENT, - returned_subnet->getDdnsReplaceClientNameMode().get()); - - EXPECT_FALSE(returned_subnet->getDdnsGeneratedPrefix().unspecified()); - EXPECT_EQ("myhost", returned_subnet->getDdnsGeneratedPrefix().get()); - - EXPECT_FALSE(returned_subnet->getDdnsQualifyingSuffix().unspecified()); - EXPECT_EQ("example.org", returned_subnet->getDdnsQualifyingSuffix().get()); - - // The easiest way to verify whether the returned subnet matches the inserted - // subnet is to convert both to text. - EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str()); -} - -// Test that subnet can be associated with a shared network. -TEST_F(PgSqlConfigBackendDHCPv6Test, getSubnet6SharedNetwork) { - Subnet6Ptr subnet = test_subnets_[0]; - SharedNetwork6Ptr shared_network = test_networks_[0]; - - // Add subnet to a shared network. - shared_network->add(subnet); - - // Store shared network in the database. - cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), shared_network); - - // Store subnet associated with the shared network in the database. - cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet); - - // Fetch this subnet by subnet identifier. - Subnet6Ptr returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(), - test_subnets_[0]->getID()); - ASSERT_TRUE(returned_subnet); - ASSERT_EQ(1, returned_subnet->getServerTags().size()); - EXPECT_EQ("all", returned_subnet->getServerTags().begin()->get()); - - // The easiest way to verify whether the returned subnet matches the inserted - // subnet is to convert both to text. - EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str()); - - // However, the check above doesn't verify whether shared network name was - // correctly returned from the database. - EXPECT_EQ(shared_network->getName(), returned_subnet->getSharedNetworkName()); -} - -// Test that subnet can be fetched by prefix. -TEST_F(PgSqlConfigBackendDHCPv6Test, getSubnet6ByPrefix) { - // Insert subnet to the database. - Subnet6Ptr subnet = test_subnets_[0]; - cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet); - - // Fetch the subnet by prefix. - Subnet6Ptr returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(), "2001:db8::/64"); - ASSERT_TRUE(returned_subnet); - ASSERT_EQ(1, returned_subnet->getServerTags().size()); - EXPECT_EQ("all", returned_subnet->getServerTags().begin()->get()); - - // Verify subnet contents. - EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str()); - - // Fetching the subnet for an explicitly specified server tag should - // succeed too. - returned_subnet = cbptr_->getSubnet6(ServerSelector::ONE("server1"), "2001:db8::/64"); - EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str()); -} - -// Test that getSubnet6 by prefix throws appropriate exceptions for various server -// selectors. -TEST_F(PgSqlConfigBackendDHCPv6Test, getSubnet6byPrefixSelectors) { - // Supported selectors. - EXPECT_NO_THROW(cbptr_->getSubnet6(ServerSelector::ANY(), "192.0.2.0/26")); - EXPECT_NO_THROW(cbptr_->getSubnet6(ServerSelector::UNASSIGNED(), "192.0.2.0/26")); - EXPECT_NO_THROW(cbptr_->getSubnet6(ServerSelector::ALL(), "192.0.2.0/26")); - EXPECT_NO_THROW(cbptr_->getSubnet6(ServerSelector::ONE("server1"), "192.0.2.0/26")); - - // Not supported selectors. - EXPECT_THROW(cbptr_->getSubnet6(ServerSelector::MULTIPLE({"server1", "server2"}), - "192.0.2.0/26"), - isc::InvalidOperation); -} - -// Test that all subnets can be fetched and then deleted. -TEST_F(PgSqlConfigBackendDHCPv6Test, getAllSubnets6) { - // Insert test subnets into the database. Note that the second subnet will - // overwrite the first subnet as they use the same ID. - for (auto subnet : test_subnets_) { - cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet); - - // That subnet overrides the first subnet so the audit entry should - // indicate an update. - if (subnet->toText() == "2001:db8:1::/48") { - SCOPED_TRACE("UPDATE audit entry for the subnet " + subnet->toText()); - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::UPDATE, "subnet set"); - - } else { - SCOPED_TRACE("CREATE audit entry for the subnet " + subnet->toText()); - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::CREATE, "subnet set"); - } - } - - // Fetch all subnets. - Subnet6Collection subnets = cbptr_->getAllSubnets6(ServerSelector::ALL()); - ASSERT_EQ(test_subnets_.size() - 1, subnets.size()); - - // All subnets should also be returned for explicitly specified server tag. - subnets = cbptr_->getAllSubnets6(ServerSelector::ONE("server1")); - ASSERT_EQ(test_subnets_.size() - 1, subnets.size()); - - // See if the subnets are returned ok. - auto subnet_it = subnets.begin(); - for (auto i = 0; i < subnets.size(); ++i, ++subnet_it) { - EXPECT_EQ(test_subnets_[i + 1]->toElement()->str(), (*subnet_it)->toElement()->str()); - ASSERT_EQ(1, (*subnet_it)->getServerTags().size()); - EXPECT_EQ("all", (*subnet_it)->getServerTags().begin()->get()); - } - - // Attempt to remove the non existing subnet should return 0. - EXPECT_EQ(0, cbptr_->deleteSubnet6(ServerSelector::ALL(), 22)); - EXPECT_EQ(0, cbptr_->deleteSubnet6(ServerSelector::ALL(), "2001:db8:555::/64")); - // All subnets should be still there. - ASSERT_EQ(test_subnets_.size() - 1, subnets.size()); - - // Should not delete the subnet for explicit server tag because - // our subnet is for all servers. - EXPECT_EQ(0, cbptr_->deleteSubnet6(ServerSelector::ONE("server1"), test_subnets_[1]->getID())); - - // Also, verify that behavior when deleting by prefix. - EXPECT_EQ(0, cbptr_->deleteSubnet6(ServerSelector::ONE("server1"), test_subnets_[2]->toText())); - - // Same for all subnets. - EXPECT_EQ(0, cbptr_->deleteAllSubnets6(ServerSelector::ONE("server1"))); - - // Delete first subnet by id and verify that it is gone. - EXPECT_EQ(1, cbptr_->deleteSubnet6(ServerSelector::ALL(), test_subnets_[1]->getID())); - - { - SCOPED_TRACE("DELETE first subnet audit entry"); - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::DELETE, "subnet deleted"); - } - - subnets = cbptr_->getAllSubnets6(ServerSelector::ALL()); - ASSERT_EQ(test_subnets_.size() - 2, subnets.size()); - - // Delete second subnet by prefix and verify it is gone. - EXPECT_EQ(1, cbptr_->deleteSubnet6(ServerSelector::ALL(), test_subnets_[2]->toText())); - subnets = cbptr_->getAllSubnets6(ServerSelector::ALL()); - ASSERT_EQ(test_subnets_.size() - 3, subnets.size()); - - { - SCOPED_TRACE("DELETE second subnet audit entry"); - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::DELETE, "subnet deleted"); - } - - // Delete all. - EXPECT_EQ(1, cbptr_->deleteAllSubnets6(ServerSelector::ALL())); - subnets = cbptr_->getAllSubnets6(ServerSelector::ALL()); - ASSERT_TRUE(subnets.empty()); - - { - SCOPED_TRACE("DELETE all subnets audit entry"); - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::DELETE, - "deleted all subnets"); - } -} - -// Test that getAllSubnets6 throws appropriate exceptions for various -// server selectors. -TEST_F(PgSqlConfigBackendDHCPv6Test, getAllSubnets6Selectors) { - // Supported selectors. - EXPECT_NO_THROW(cbptr_->getAllSubnets6(ServerSelector::UNASSIGNED())); - EXPECT_NO_THROW(cbptr_->getAllSubnets6(ServerSelector::ALL())); - EXPECT_NO_THROW(cbptr_->getAllSubnets6(ServerSelector::ONE("server1"))); - EXPECT_NO_THROW(cbptr_->getAllSubnets6(ServerSelector::MULTIPLE({"server1", "server2"}))); - - // Not supported selectors. - EXPECT_THROW(cbptr_->getAllSubnets6(ServerSelector::ANY()), isc::InvalidOperation); -} - -// Test that subnets with different server associations are returned. -TEST_F(PgSqlConfigBackendDHCPv6Test, getAllSubnets6WithServerTags) { - auto subnet1 = test_subnets_[0]; - auto subnet2 = test_subnets_[2]; - auto subnet3 = test_subnets_[3]; - - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[0])); - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[2])); - - EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet1)); - EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ONE("server1"), subnet2)); - EXPECT_NO_THROW( - cbptr_->createUpdateSubnet6(ServerSelector::MULTIPLE({"server1", "server2"}), subnet3)); - - Subnet6Collection subnets; - - // All three subnets are associated with the server1. - EXPECT_NO_THROW(subnets = cbptr_->getAllSubnets6(ServerSelector::ONE("server1"))); - EXPECT_EQ(3, subnets.size()); - - // First subnet is associated with all servers. - auto returned_subnet = SubnetFetcher6::get(subnets, SubnetID(1024)); - ASSERT_TRUE(returned_subnet); - EXPECT_TRUE(returned_subnet->hasAllServerTag()); - EXPECT_FALSE(returned_subnet->hasServerTag(ServerTag("server1"))); - EXPECT_FALSE(returned_subnet->hasServerTag(ServerTag("server2"))); - - // Second subnet is only associated with the server1. - returned_subnet = SubnetFetcher6::get(subnets, SubnetID(2048)); - ASSERT_TRUE(returned_subnet); - EXPECT_FALSE(returned_subnet->hasAllServerTag()); - EXPECT_TRUE(returned_subnet->hasServerTag(ServerTag("server1"))); - EXPECT_FALSE(returned_subnet->hasServerTag(ServerTag("server2"))); - - // Third subnet is associated with both server1 and server2. - returned_subnet = SubnetFetcher6::get(subnets, SubnetID(4096)); - ASSERT_TRUE(returned_subnet); - EXPECT_FALSE(returned_subnet->hasAllServerTag()); - EXPECT_TRUE(returned_subnet->hasServerTag(ServerTag("server1"))); - EXPECT_TRUE(returned_subnet->hasServerTag(ServerTag("server2"))); - - // For server2 we should only get two subnets, i.e. first and last. - EXPECT_NO_THROW(subnets = cbptr_->getAllSubnets6(ServerSelector::ONE("server2"))); - EXPECT_EQ(2, subnets.size()); - - // First subnet is associated with all servers. - returned_subnet = SubnetFetcher6::get(subnets, SubnetID(1024)); - ASSERT_TRUE(returned_subnet); - EXPECT_TRUE(returned_subnet->hasAllServerTag()); - EXPECT_FALSE(returned_subnet->hasServerTag(ServerTag("server1"))); - EXPECT_FALSE(returned_subnet->hasServerTag(ServerTag("server2"))); - - // Last subnet is associated with server1 and server2. - returned_subnet = SubnetFetcher6::get(subnets, SubnetID(4096)); - ASSERT_TRUE(returned_subnet); - EXPECT_FALSE(returned_subnet->hasAllServerTag()); - EXPECT_TRUE(returned_subnet->hasServerTag(ServerTag("server1"))); - EXPECT_TRUE(returned_subnet->hasServerTag(ServerTag("server2"))); - - // Only the first subnet is associated with all servers. - EXPECT_NO_THROW(subnets = cbptr_->getAllSubnets6(ServerSelector::ALL())); - EXPECT_EQ(1, subnets.size()); - - returned_subnet = SubnetFetcher6::get(subnets, SubnetID(1024)); - ASSERT_TRUE(returned_subnet); - EXPECT_TRUE(returned_subnet->hasAllServerTag()); - EXPECT_FALSE(returned_subnet->hasServerTag(ServerTag("server1"))); - EXPECT_FALSE(returned_subnet->hasServerTag(ServerTag("server2"))); -} - -// Test that selected subnet can be deleted. -TEST_F(PgSqlConfigBackendDHCPv6Test, deleteSubnet6) { - // Create two servers in the database. - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[0])); - { - SCOPED_TRACE("CREATE audit entry for server"); - testNewAuditEntry("dhcp6_server", AuditEntry::ModificationType::CREATE, "server set"); - } - - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[2])); - { - SCOPED_TRACE("CREATE audit entry for server"); - testNewAuditEntry("dhcp6_server", AuditEntry::ModificationType::CREATE, "server set"); - } - - auto subnet1 = test_subnets_[0]; - auto subnet2 = test_subnets_[2]; - auto subnet3 = test_subnets_[3]; - - auto create_test_subnets = [&]() { - // Insert three subnets, one for all servers, one for server2 and one for two - // servers: server1 and server2. - EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet1)); - EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ONE("server2"), subnet2)); - EXPECT_NO_THROW( - cbptr_->createUpdateSubnet6(ServerSelector::MULTIPLE({"server1", "server2"}), subnet3)); - }; - - create_test_subnets(); - - // Test that subnet is not deleted for a specified server selector. - auto test_no_delete = [this](const std::string& test_case_name, - const ServerSelector& server_selector, const Subnet6Ptr& subnet) { - SCOPED_TRACE(test_case_name); - uint64_t deleted_count = 0; - EXPECT_NO_THROW(deleted_count = cbptr_->deleteSubnet6(server_selector, subnet->getID())); - EXPECT_EQ(0, deleted_count); - - deleted_count = 0; - EXPECT_NO_THROW(deleted_count = cbptr_->deleteSubnet6(server_selector, subnet->toText())); - EXPECT_EQ(0, deleted_count); - }; - - { - SCOPED_TRACE("Test valid but non matching server selectors"); - test_no_delete("selector: one, actual: all", ServerSelector::ONE("server2"), subnet1); - test_no_delete("selector: all, actual: one", ServerSelector::ALL(), subnet2); - test_no_delete("selector: all, actual: multiple", ServerSelector::ALL(), subnet3); - } - - // Test successful deletion of a subnet by ID. - auto test_delete_by_id = [this](const std::string& test_case_name, - const ServerSelector& server_selector, - const Subnet6Ptr& subnet) { - SCOPED_TRACE(test_case_name); - uint64_t deleted_count = 0; - EXPECT_NO_THROW(deleted_count = cbptr_->deleteSubnet6(server_selector, subnet->getID())); - EXPECT_EQ(1, deleted_count); - - EXPECT_FALSE(cbptr_->getSubnet6(server_selector, subnet->getID())); - }; - - test_delete_by_id("all servers", ServerSelector::ALL(), subnet1); - test_delete_by_id("any server", ServerSelector::ANY(), subnet2); - test_delete_by_id("one server", ServerSelector::ONE("server1"), subnet3); - - // Re-create deleted subnets. - create_test_subnets(); - - // Test successful deletion of a subnet by prefix. - auto test_delete_by_prefix = [this](const std::string& test_case_name, - const ServerSelector& server_selector, - const Subnet6Ptr& subnet) { - SCOPED_TRACE(test_case_name); - uint64_t deleted_count = 0; - EXPECT_NO_THROW(deleted_count = cbptr_->deleteSubnet6(server_selector, subnet->toText())); - EXPECT_EQ(1, deleted_count); - - EXPECT_FALSE(cbptr_->getSubnet6(server_selector, subnet->toText())); - }; - - test_delete_by_prefix("all servers", ServerSelector::ALL(), subnet1); - test_delete_by_prefix("any server", ServerSelector::ANY(), subnet2); - test_delete_by_prefix("one server", ServerSelector::ONE("server1"), subnet3); -} - -// Test that deleteSubnet6 by ID throws appropriate exceptions for various -// server selectors. -TEST_F(PgSqlConfigBackendDHCPv6Test, deleteSubnet6ByIdSelectors) { - // Supported selectors. - EXPECT_NO_THROW(cbptr_->deleteSubnet6(ServerSelector::ANY(), SubnetID(1))); - EXPECT_NO_THROW(cbptr_->deleteSubnet6(ServerSelector::ALL(), SubnetID(1))); - EXPECT_NO_THROW(cbptr_->deleteSubnet6(ServerSelector::ONE("server1"), SubnetID(1))); - - // Not supported selectors. - EXPECT_THROW(cbptr_->deleteSubnet6(ServerSelector::MULTIPLE({"server1", "server2"}), - SubnetID(1)), - isc::InvalidOperation); - - // Not implemented selectors. - EXPECT_THROW(cbptr_->deleteSubnet6(ServerSelector::UNASSIGNED(), SubnetID(1)), - isc::NotImplemented); -} - -// Test that deleteSubnet6 by prefix throws appropriate exceptions for various -// server selectors. -TEST_F(PgSqlConfigBackendDHCPv6Test, deleteSubnet6ByPrefixSelectors) { - // Supported selectors. - EXPECT_NO_THROW(cbptr_->deleteSubnet6(ServerSelector::ANY(), "192.0.2.0/26")); - EXPECT_NO_THROW(cbptr_->deleteSubnet6(ServerSelector::ALL(), "192.0.2.0/26")); - EXPECT_NO_THROW(cbptr_->deleteSubnet6(ServerSelector::ONE("server1"), "192.0.2.0/26")); - - // Not supported selectors. - EXPECT_THROW(cbptr_->deleteSubnet6(ServerSelector::MULTIPLE({"server1", "server2"}), - "192.0.2.0/26"), - isc::InvalidOperation); - - // Not implemented selectors. - EXPECT_THROW(cbptr_->deleteSubnet6(ServerSelector::UNASSIGNED(), "192.0.2.0/26"), - isc::NotImplemented); -} - -// Test that deleteAllSubnets6 throws appropriate exceptions for various -// server selectors. -TEST_F(PgSqlConfigBackendDHCPv6Test, deleteAllSubnets6Selectors) { - // Supported selectors. - EXPECT_NO_THROW(cbptr_->deleteAllSubnets6(ServerSelector::UNASSIGNED())); - EXPECT_NO_THROW(cbptr_->deleteAllSubnets6(ServerSelector::ALL())); - EXPECT_NO_THROW(cbptr_->deleteAllSubnets6(ServerSelector::ONE("server1"))); - - // Not supported selectors. - EXPECT_THROW(cbptr_->deleteAllSubnets6(ServerSelector::ANY()), isc::InvalidOperation); - EXPECT_THROW(cbptr_->deleteAllSubnets6(ServerSelector::MULTIPLE({"server1", "server2"})), - isc::InvalidOperation); -} - -// Test that it is possible to retrieve and delete orphaned subnet. -TEST_F(PgSqlConfigBackendDHCPv6Test, unassignedSubnet6) { - // Create the server. - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[0])); - - // Create the subnets and associate them with the server1. - auto subnet = test_subnets_[0]; - auto subnet2 = test_subnets_[2]; - EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ONE("server1"), subnet)); - EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ONE("server1"), subnet2)); - - // Delete the server. The subnets should be preserved but are considered orphaned, - // i.e. do not belong to any server. - uint64_t deleted_count = 0; - EXPECT_NO_THROW(deleted_count = cbptr_->deleteServer6(ServerTag("server1"))); - EXPECT_EQ(1, deleted_count); - - // Trying to fetch the subnet by server tag should return no result. - Subnet6Ptr returned_subnet; - EXPECT_NO_THROW( - returned_subnet = cbptr_->getSubnet6(ServerSelector::ONE("server1"), subnet->getID())); - EXPECT_FALSE(returned_subnet); - - // The same if we use other calls. - EXPECT_NO_THROW( - returned_subnet = cbptr_->getSubnet6(ServerSelector::ONE("server1"), subnet->toText())); - EXPECT_FALSE(returned_subnet); - - Subnet6Collection returned_subnets; - EXPECT_NO_THROW(returned_subnets = cbptr_->getAllSubnets6(ServerSelector::ONE("server1"))); - EXPECT_TRUE(returned_subnets.empty()); - - EXPECT_NO_THROW(returned_subnets = cbptr_->getModifiedSubnets6(ServerSelector::ONE("server1"), - timestamps_["two days ago"])); - EXPECT_TRUE(returned_subnets.empty()); - - // We should get the subnet if we ask for unassigned. - EXPECT_NO_THROW( - returned_subnet = cbptr_->getSubnet6(ServerSelector::UNASSIGNED(), subnet->getID())); - ASSERT_TRUE(returned_subnet); - - EXPECT_NO_THROW( - returned_subnet = cbptr_->getSubnet6(ServerSelector::UNASSIGNED(), subnet->toText())); - ASSERT_TRUE(returned_subnet); - - // Also if we ask for all unassigned subnets it should be returned. - EXPECT_NO_THROW(returned_subnets = cbptr_->getAllSubnets6(ServerSelector::UNASSIGNED())); - ASSERT_EQ(2, returned_subnets.size()); - - // Same for modified subnets. - EXPECT_NO_THROW(returned_subnets = cbptr_->getModifiedSubnets6(ServerSelector::UNASSIGNED(), - timestamps_["two days ago"])); - ASSERT_EQ(2, returned_subnets.size()); - - // If we ask for any subnet by subnet id, it should be returned too. - EXPECT_NO_THROW(returned_subnet = cbptr_->getSubnet6(ServerSelector::ANY(), subnet->getID())); - ASSERT_TRUE(returned_subnet); - - EXPECT_NO_THROW(returned_subnet = cbptr_->getSubnet6(ServerSelector::ANY(), subnet->toText())); - ASSERT_TRUE(returned_subnet); - - // Deleting the subnet with the mismatched server tag should not affect our - // subnet. - EXPECT_NO_THROW( - deleted_count = cbptr_->deleteSubnet6(ServerSelector::ONE("server1"), subnet->getID())); - EXPECT_EQ(0, deleted_count); - - // Also, if we delete all subnets for server1. - EXPECT_NO_THROW(deleted_count = cbptr_->deleteAllSubnets6(ServerSelector::ONE("server1"))); - EXPECT_EQ(0, deleted_count); - - // We can delete this subnet when we specify ANY and the matching id. - EXPECT_NO_THROW(deleted_count = cbptr_->deleteSubnet6(ServerSelector::ANY(), subnet->getID())); - EXPECT_EQ(1, deleted_count); - - // We can delete all subnets using UNASSIGNED selector. - EXPECT_NO_THROW(deleted_count = cbptr_->deleteAllSubnets6(ServerSelector::UNASSIGNED());); - EXPECT_EQ(1, deleted_count); -} - -// Test that subnets modified after given time can be fetched. -TEST_F(PgSqlConfigBackendDHCPv6Test, getModifiedSubnets6) { - // Explicitly set timestamps of subnets. First subnet has a timestamp - // pointing to the future. Second subnet has timestamp pointing to the - // past (yesterday). Third subnet has a timestamp pointing to the - // past (an hour ago). - test_subnets_[1]->setModificationTime(timestamps_["tomorrow"]); - test_subnets_[2]->setModificationTime(timestamps_["yesterday"]); - test_subnets_[3]->setModificationTime(timestamps_["today"]); - - // Insert subnets into the database. - for (int i = 1; i < test_subnets_.size(); ++i) { - cbptr_->createUpdateSubnet6(ServerSelector::ALL(), test_subnets_[i]); - } - - // Fetch subnets with timestamp later than today. Only one subnet - // should be returned. - Subnet6Collection subnets = cbptr_->getModifiedSubnets6(ServerSelector::ALL(), - timestamps_["after today"]); - ASSERT_EQ(1, subnets.size()); - - // All subnets should also be returned for explicitly specified server tag. - subnets = cbptr_->getModifiedSubnets6(ServerSelector::ONE("server1"), - timestamps_["after today"]); - ASSERT_EQ(1, subnets.size()); - - // Fetch subnets with timestamp later than yesterday. We should get - // two subnets. - subnets = cbptr_->getModifiedSubnets6(ServerSelector::ALL(), timestamps_["after yesterday"]); - ASSERT_EQ(2, subnets.size()); - - // Fetch subnets with timestamp later than tomorrow. Nothing should - // be returned. - subnets = cbptr_->getModifiedSubnets6(ServerSelector::ALL(), timestamps_["after tomorrow"]); - ASSERT_TRUE(subnets.empty()); -} - -// Test that getModifiedSubnets6 throws appropriate exceptions for various -// server selectors. -TEST_F(PgSqlConfigBackendDHCPv6Test, getModifiedSubnets6Selectors) { - // Supported selectors. - EXPECT_NO_THROW( - cbptr_->getModifiedSubnets6(ServerSelector::UNASSIGNED(), timestamps_["yesterday"])); - EXPECT_NO_THROW(cbptr_->getModifiedSubnets6(ServerSelector::ALL(), timestamps_["yesterday"])); - EXPECT_NO_THROW( - cbptr_->getModifiedSubnets6(ServerSelector::ONE("server1"), timestamps_["yesterday"])); - EXPECT_NO_THROW(cbptr_->getModifiedSubnets6(ServerSelector::MULTIPLE({"server1", "server2"}), - timestamps_["yesterday"])); - - // Not supported selectors. - EXPECT_THROW(cbptr_->getModifiedSubnets6(ServerSelector::ANY(), timestamps_["yesterday"]), - isc::InvalidOperation); -} - -// Test that lifetimes in subnets are handled as expected. -TEST_F(PgSqlConfigBackendDHCPv6Test, subnetLifetime) { - // Insert new subnet with unspecified valid lifetime - Triplet unspecified; - Subnet6Ptr subnet( - new Subnet6(IOAddress("2001:db8::"), 64, 30, 40, unspecified, unspecified, 1111)); - subnet->setIface("eth1"); - cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet); - - // Fetch this subnet by subnet identifier - Subnet6Ptr returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(), subnet->getID()); - ASSERT_TRUE(returned_subnet); - - // Verified returned and original subnets match. - EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str()); - - // Update the preferred and valid lifetime. - subnet->setPreferred(Triplet(100, 200, 300)); - subnet->setValid(Triplet(200, 300, 400)); - cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet); - - // Fetch and verify again. - returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(), subnet->getID()); - ASSERT_TRUE(returned_subnet); - EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str()); -} - -// Test that subnets belonging to a shared network can be retrieved. -TEST_F(PgSqlConfigBackendDHCPv6Test, getSharedNetworkSubnets6) { - // Assign test subnets to shared networks level1 and level2. - test_subnets_[1]->setSharedNetworkName("level1"); - test_subnets_[2]->setSharedNetworkName("level2"); - test_subnets_[3]->setSharedNetworkName("level2"); - - // Store shared networks in the database. - for (auto network : test_networks_) { - cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), network); - } - - // Store subnets in the database. - for (auto subnet : test_subnets_) { - cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet); - } - - // Fetch all subnets belonging to shared network level1. - Subnet6Collection subnets = cbptr_->getSharedNetworkSubnets6(ServerSelector::ALL(), "level1"); - ASSERT_EQ(1, subnets.size()); - - // Returned subnet should match test subnet #1. - EXPECT_TRUE(isEquivalent(test_subnets_[1]->toElement(), (*subnets.begin())->toElement())); - - // All subnets should also be returned for ANY server. - subnets = cbptr_->getSharedNetworkSubnets6(ServerSelector::ANY(), "level1"); - ASSERT_EQ(1, subnets.size()); - - // Returned subnet should match test subnet #1. - EXPECT_TRUE(isEquivalent(test_subnets_[1]->toElement(), (*subnets.begin())->toElement())); - - // Fetch all subnets belonging to shared network level2. - subnets = cbptr_->getSharedNetworkSubnets6(ServerSelector::ALL(), "level2"); - ASSERT_EQ(2, subnets.size()); - - ElementPtr test_list = Element::createList(); - test_list->add(test_subnets_[2]->toElement()); - test_list->add(test_subnets_[3]->toElement()); - - ElementPtr returned_list = Element::createList(); - auto subnet = subnets.begin(); - returned_list->add((*subnet)->toElement()); - returned_list->add((*++subnet)->toElement()); - - EXPECT_TRUE(isEquivalent(returned_list, test_list)); - - // All subnets should also be returned for explicitly specified server tag. - subnets = cbptr_->getSharedNetworkSubnets6(ServerSelector::ONE("server1"), "level2"); - ASSERT_EQ(2, subnets.size()); - - returned_list = Element::createList(); - subnet = subnets.begin(); - returned_list->add((*subnet)->toElement()); - returned_list->add((*++subnet)->toElement()); - - EXPECT_TRUE(isEquivalent(returned_list, test_list)); -} - -// Test that pools are properly updated as a result a subnet update. -TEST_F(PgSqlConfigBackendDHCPv6Test, subnetUpdatePools) { - - auto test_subnet_update = [this](const std::string& subnet_prefix, const SubnetID& subnet_id) { - // Add the subnet with two address pools and two prefix delegation - // pools. - EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ALL(), test_subnets_[0])); - // Make sure that the pools have been added to the database. - EXPECT_EQ(2, countRows("dhcp6_pool")); - EXPECT_EQ(2, countRows("dhcp6_pd_pool")); - - // Create the subnet without options which updates the existing - // subnet. - Subnet6Ptr subnet(new Subnet6(IOAddress(subnet_prefix), 64, 30, 60, 50, 60, subnet_id)); - EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet)); - // Check that options are gone. - EXPECT_EQ(0, countRows("dhcp6_pool")); - EXPECT_EQ(0, countRows("dhcp6_pd_pool")); - }; - - { - SCOPED_TRACE("update subnet, modify subnet id"); - // Create another subnet with the same prefix as the original subnet but - // different id. This is legal to update the subnet id if the prefix is - // stable. However, the new subnet has no address pools, so we need to - // check of the pools associated with the existing subnet instance are - // gone after the update. - test_subnet_update("2001:db8::", 2048); - } - - { - SCOPED_TRACE("update subnet, modify prefix"); - // Create a subnet with the same subnet id but different prefix. - // The prefix should be updated. - test_subnet_update("2001:db9::", 1024); - } -} - -// Test that deleting a subnet triggers deletion of the options associated -// with the subnet and pools. -TEST_F(PgSqlConfigBackendDHCPv6Test, subnetOptions) { - // Add the subnet with two pools and three options. - EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ALL(), test_subnets_[0])); - EXPECT_EQ(2, countRows("dhcp6_pool")); - EXPECT_EQ(2, countRows("dhcp6_pd_pool")); - EXPECT_EQ(3, countRows("dhcp6_options")); - - // The second subnet uses the same subnet id, so this operation should replace - // the existing subnet and its options. The new instance has four pools, each - // including one option, so we should end up with four options. - EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ALL(), test_subnets_[1])); - EXPECT_EQ(2, countRows("dhcp6_pool")); - EXPECT_EQ(2, countRows("dhcp6_pd_pool")); - EXPECT_EQ(4, countRows("dhcp6_options")); - - // Add third subnet with a single option. The number of options in the database - // should now be 5. - EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ALL(), test_subnets_[2])); - EXPECT_EQ(2, countRows("dhcp6_pool")); - EXPECT_EQ(2, countRows("dhcp6_pd_pool")); - EXPECT_EQ(5, countRows("dhcp6_options")); - - // Delete the subnet. All options and pools it contains should also be removed, leaving - // the last added subnet and its sole option. - EXPECT_NO_THROW(cbptr_->deleteSubnet6(ServerSelector::ALL(), test_subnets_[1]->getID())); - EXPECT_EQ(1, countRows("dhcp6_subnet")); - EXPECT_EQ(0, countRows("dhcp6_pool")); - EXPECT_EQ(0, countRows("dhcp6_pd_pool")); - EXPECT_EQ(1, countRows("dhcp6_options")); - - // Add the first subnet again. We should now have 4 options: 3 options from the - // newly added subnet and one option from the existing subnet. - EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ALL(), test_subnets_[0])); - EXPECT_EQ(2, countRows("dhcp6_pool")); - EXPECT_EQ(2, countRows("dhcp6_pd_pool")); - EXPECT_EQ(4, countRows("dhcp6_options")); - - // Delete the subnet including 3 options. The option from the other subnet should not - // be affected. - EXPECT_NO_THROW(cbptr_->deleteSubnet6(ServerSelector::ALL(), test_subnets_[0]->getID())); - EXPECT_EQ(1, countRows("dhcp6_subnet")); - EXPECT_EQ(0, countRows("dhcp6_pool")); - EXPECT_EQ(0, countRows("dhcp6_pd_pool")); - EXPECT_EQ(1, countRows("dhcp6_options")); -} - -// Test that shared network can be inserted, fetched, updated and then -// fetched again. -TEST_F(PgSqlConfigBackendDHCPv6Test, getSharedNetwork6) { - // Insert the server2 into the database. - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[2])); - { - SCOPED_TRACE("CREATE audit entry for server"); - testNewAuditEntry("dhcp6_server", AuditEntry::ModificationType::CREATE, "server set"); - } - - auto shared_network = test_networks_[0]; - auto shared_network2 = test_networks_[2]; - - // Insert two shared networks, one for all servers, and one for server2. - EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), shared_network)); - EXPECT_NO_THROW( - cbptr_->createUpdateSharedNetwork6(ServerSelector::ONE("server2"), shared_network2)); - - // We are not going to support selection of a single entry for multiple servers. - EXPECT_THROW(cbptr_->getSharedNetwork6(ServerSelector::MULTIPLE({"server1", "server2"}), - test_networks_[0]->getName()), - isc::InvalidOperation); - - // Test that this shared network will be fetched for various server selectors. - auto test_get_network = [this, - &shared_network](const std::string& test_case_name, - const ServerSelector& server_selector, - const std::string& expected_tag = ServerTag::ALL) { - SCOPED_TRACE(test_case_name); - SharedNetwork6Ptr network; - ASSERT_NO_THROW( - network = cbptr_->getSharedNetwork6(server_selector, shared_network->getName())); - ASSERT_TRUE(network); - - EXPECT_GT(network->getId(), 0); - ASSERT_EQ(1, network->getServerTags().size()); - EXPECT_EQ(expected_tag, network->getServerTags().begin()->get()); - - // The easiest way to verify whether the returned shared network matches the - // inserted shared network is to convert both to text. - EXPECT_EQ(shared_network->toElement()->str(), network->toElement()->str()); - }; - - { - SCOPED_TRACE("testing various server selectors before update"); - test_get_network("all servers", ServerSelector::ALL()); - test_get_network("one server", ServerSelector::ONE("server1")); - test_get_network("any server", ServerSelector::ANY()); - } - - { - SCOPED_TRACE("CREATE audit entry for a shared network"); - testNewAuditEntry("dhcp6_shared_network", AuditEntry::ModificationType::CREATE, - "shared network set"); - } - - // Update shared network in the database. - shared_network = test_networks_[1]; - EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), shared_network)); - - { - SCOPED_TRACE("testing various server selectors after update"); - test_get_network("all servers after update", ServerSelector::ALL()); - test_get_network("one server after update", ServerSelector::ONE("server1")); - test_get_network("any server after update", ServerSelector::ANY()); - } - - { - SCOPED_TRACE("UPDATE audit entry for a shared network"); - testNewAuditEntry("dhcp6_shared_network", AuditEntry::ModificationType::UPDATE, - "shared network set"); - } - - // The server2 specific shared network should not be returned if the - // server selector is not matching. - EXPECT_FALSE(cbptr_->getSharedNetwork6(ServerSelector::ALL(), shared_network2->getName())); - EXPECT_FALSE( - cbptr_->getSharedNetwork6(ServerSelector::ONE("server1"), shared_network2->getName())); - - { - SCOPED_TRACE("testing selectors for server2 specific shared network"); - shared_network = shared_network2; - test_get_network("one server", ServerSelector::ONE("server2"), "server2"); - test_get_network("any server", ServerSelector::ANY(), "server2"); - } -} - -// Test that getSharedNetwork6 throws appropriate exceptions for various -// server selectors. -TEST_F(PgSqlConfigBackendDHCPv6Test, getSharedNetwork6Selectors) { - // Supported selectors. - EXPECT_NO_THROW(cbptr_->getSharedNetwork6(ServerSelector::ANY(), "level1")); - EXPECT_NO_THROW(cbptr_->getSharedNetwork6(ServerSelector::UNASSIGNED(), "level1")); - EXPECT_NO_THROW(cbptr_->getSharedNetwork6(ServerSelector::ALL(), "level1")); - EXPECT_NO_THROW(cbptr_->getSharedNetwork6(ServerSelector::ONE("server1"), "level1")); - - // Not supported selectors. - EXPECT_THROW(cbptr_->getSharedNetwork6(ServerSelector::MULTIPLE({"server1", "server2"}), - "level1"), - isc::InvalidOperation); -} - -// Test that shared network may be created and updated and the server tags -// are properly assigned to it. -TEST_F(PgSqlConfigBackendDHCPv6Test, createUpdateSharedNetwork6) { - auto shared_network = test_networks_[0]; - - // An attempt to insert the shared network for non-existing server should fail. - EXPECT_THROW(cbptr_->createUpdateSharedNetwork6(ServerSelector::ONE("server1"), shared_network), - NullKeyError); - - // Insert the server1 into the database. - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[0])); - { - SCOPED_TRACE("CREATE audit entry for server"); - testNewAuditEntry("dhcp6_server", AuditEntry::ModificationType::CREATE, "server set"); - } - - // Insert the server2 into the database. - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[2])); - { - SCOPED_TRACE("CREATE audit entry for server"); - testNewAuditEntry("dhcp6_server", AuditEntry::ModificationType::CREATE, "server set"); - } - - EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), shared_network)); - { - SCOPED_TRACE("CREATE audit entry for shared network and ALL servers"); - testNewAuditEntry("dhcp6_shared_network", AuditEntry::ModificationType::CREATE, - "shared network set"); - } - - EXPECT_NO_THROW( - cbptr_->createUpdateSharedNetwork6(ServerSelector::MULTIPLE({"server1", "server2"}), - shared_network)); - { - SCOPED_TRACE("UPDATE audit entry for shared network and MULTIPLE servers"); - testNewAuditEntry("dhcp6_shared_network", AuditEntry::ModificationType::UPDATE, - "shared network set"); - } - - SharedNetwork6Ptr network; - ASSERT_NO_THROW( - network = cbptr_->getSharedNetwork6(ServerSelector::ANY(), shared_network->getName())); - ASSERT_TRUE(network); - EXPECT_TRUE(network->hasServerTag(ServerTag("server1"))); - EXPECT_TRUE(network->hasServerTag(ServerTag("server2"))); - EXPECT_FALSE(network->hasServerTag(ServerTag())); -} - -// Test that createUpdateSharedNetwork6 throws appropriate exceptions for various -// server selectors. -TEST_F(PgSqlConfigBackendDHCPv6Test, createUpdateSharedNetwork6Selectors) { - ASSERT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[0])); - ASSERT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[2])); - - // Supported selectors. - SharedNetwork6Ptr shared_network(new SharedNetwork6("all")); - EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), shared_network)); - shared_network.reset(new SharedNetwork6("one")); - EXPECT_NO_THROW( - cbptr_->createUpdateSharedNetwork6(ServerSelector::ONE("server1"), shared_network)); - shared_network.reset(new SharedNetwork6("multiple")); - EXPECT_NO_THROW( - cbptr_->createUpdateSharedNetwork6(ServerSelector::MULTIPLE({"server1", "server2"}), - shared_network)); - - // Not supported server selectors. - EXPECT_THROW(cbptr_->createUpdateSharedNetwork6(ServerSelector::ANY(), shared_network), - isc::InvalidOperation); - - // Not implemented server selectors. - EXPECT_THROW(cbptr_->createUpdateSharedNetwork6(ServerSelector::UNASSIGNED(), shared_network), - isc::NotImplemented); -} - -// Test that the information about unspecified optional parameters gets -// propagated to the database. -TEST_F(PgSqlConfigBackendDHCPv6Test, getSharedNetwork6WithOptionalUnspecified) { - // Insert new shared network. - SharedNetwork6Ptr shared_network = test_networks_[2]; - cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), shared_network); - - // Fetch this shared network by name. - SharedNetwork6Ptr returned_network = cbptr_->getSharedNetwork6(ServerSelector::ALL(), - test_networks_[2]->getName()); - ASSERT_TRUE(returned_network); - - EXPECT_TRUE(returned_network->getIface().unspecified()); - EXPECT_TRUE(returned_network->getIface().empty()); - - EXPECT_TRUE(returned_network->getClientClass().unspecified()); - EXPECT_TRUE(returned_network->getClientClass().empty()); - - EXPECT_TRUE(returned_network->getValid().unspecified()); - EXPECT_EQ(0, returned_network->getValid().get()); - - EXPECT_TRUE(returned_network->getPreferred().unspecified()); - EXPECT_EQ(0, returned_network->getPreferred().get()); - - EXPECT_TRUE(returned_network->getT1().unspecified()); - EXPECT_EQ(0, returned_network->getT1().get()); - - EXPECT_TRUE(returned_network->getT2().unspecified()); - EXPECT_EQ(0, returned_network->getT2().get()); - - EXPECT_TRUE(returned_network->getReservationsGlobal().unspecified()); - EXPECT_FALSE(returned_network->getReservationsGlobal().get()); - - EXPECT_TRUE(returned_network->getReservationsInSubnet().unspecified()); - EXPECT_TRUE(returned_network->getReservationsInSubnet().get()); - - EXPECT_TRUE(returned_network->getReservationsOutOfPool().unspecified()); - EXPECT_FALSE(returned_network->getReservationsOutOfPool().get()); - - EXPECT_TRUE(returned_network->getCalculateTeeTimes().unspecified()); - EXPECT_FALSE(returned_network->getCalculateTeeTimes().get()); - - EXPECT_TRUE(returned_network->getT1Percent().unspecified()); - EXPECT_EQ(0.0, returned_network->getT1Percent().get()); - - EXPECT_TRUE(returned_network->getT2Percent().unspecified()); - EXPECT_EQ(0.0, returned_network->getT2Percent().get()); - - EXPECT_TRUE(returned_network->getRapidCommit().unspecified()); - EXPECT_FALSE(returned_network->getRapidCommit().get()); - - EXPECT_FALSE(returned_network->getDdnsSendUpdates().unspecified()); - EXPECT_TRUE(returned_network->getDdnsSendUpdates().get()); - - EXPECT_FALSE(returned_network->getDdnsOverrideNoUpdate().unspecified()); - EXPECT_TRUE(returned_network->getDdnsOverrideNoUpdate().get()); - - EXPECT_FALSE(returned_network->getDdnsOverrideClientUpdate().unspecified()); - EXPECT_FALSE(returned_network->getDdnsOverrideClientUpdate().get()); - - EXPECT_FALSE(returned_network->getDdnsReplaceClientNameMode().unspecified()); - EXPECT_EQ(D2ClientConfig::ReplaceClientNameMode::RCM_WHEN_PRESENT, - returned_network->getDdnsReplaceClientNameMode().get()); - - EXPECT_FALSE(returned_network->getDdnsGeneratedPrefix().unspecified()); - EXPECT_EQ("myhost", returned_network->getDdnsGeneratedPrefix().get()); - - EXPECT_FALSE(returned_network->getDdnsQualifyingSuffix().unspecified()); - EXPECT_EQ("example.org", returned_network->getDdnsQualifyingSuffix().get()); -} - -// Test that deleteSharedNetworkSubnets6 with not ANY selector throw. -TEST_F(PgSqlConfigBackendDHCPv6Test, deleteSharedNetworkSubnets6) { - EXPECT_THROW(cbptr_->deleteSharedNetworkSubnets6(ServerSelector::UNASSIGNED(), - test_networks_[1]->getName()), - isc::InvalidOperation); - EXPECT_THROW(cbptr_->deleteSharedNetworkSubnets6(ServerSelector::ALL(), - test_networks_[1]->getName()), - isc::InvalidOperation); - EXPECT_THROW(cbptr_->deleteSharedNetworkSubnets6(ServerSelector::ONE("server1"), - test_networks_[1]->getName()), - isc::InvalidOperation); - EXPECT_THROW(cbptr_->deleteSharedNetworkSubnets6(ServerSelector::MULTIPLE({"server1", "server" - "2"}), - test_networks_[1]->getName()), - isc::InvalidOperation); -} - -// Test that all shared networks can be fetched. -TEST_F(PgSqlConfigBackendDHCPv6Test, getAllSharedNetworks6) { - // Insert test shared networks into the database. Note that the second shared - // network will overwrite the first shared network as they use the same name. - for (auto network : test_networks_) { - cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), network); - - // That shared network overrides the first one so the audit entry should - // indicate an update. - if ((network->getName() == "level1") && (!audit_entries_["all"].empty())) { - SCOPED_TRACE("UPDATE audit entry for the shared network " + network->getName()); - testNewAuditEntry("dhcp6_shared_network", AuditEntry::ModificationType::UPDATE, - "shared network set"); - - } else { - SCOPED_TRACE("CREATE audit entry for the shared network " + network->getName()); - testNewAuditEntry("dhcp6_shared_network", AuditEntry::ModificationType::CREATE, - "shared network set"); - } - } - - // Fetch all shared networks. - SharedNetwork6Collection networks = cbptr_->getAllSharedNetworks6(ServerSelector::ALL()); - ASSERT_EQ(test_networks_.size() - 1, networks.size()); - - // All shared networks should also be returned for explicitly specified - // server tag. - networks = cbptr_->getAllSharedNetworks6(ServerSelector::ONE("server1")); - ASSERT_EQ(test_networks_.size() - 1, networks.size()); - - // See if shared networks are returned ok. - for (auto i = 0; i < networks.size(); ++i) { - EXPECT_EQ(test_networks_[i + 1]->toElement()->str(), networks[i]->toElement()->str()); - ASSERT_EQ(1, networks[i]->getServerTags().size()); - EXPECT_EQ("all", networks[i]->getServerTags().begin()->get()); - } - - // Add some subnets. - test_networks_[1]->add(test_subnets_[0]); - test_subnets_[2]->setSharedNetworkName("level2"); - test_networks_[2]->add(test_subnets_[3]); - cbptr_->createUpdateSubnet6(ServerSelector::ALL(), test_subnets_[0]); - cbptr_->createUpdateSubnet6(ServerSelector::ALL(), test_subnets_[2]); - cbptr_->createUpdateSubnet6(ServerSelector::ALL(), test_subnets_[3]); - - // Both ways to attach a subnet are equivalent. - Subnet6Ptr subnet = cbptr_->getSubnet6(ServerSelector::ALL(), test_subnets_[0]->getID()); - ASSERT_TRUE(subnet); - EXPECT_EQ("level1", subnet->getSharedNetworkName()); - - { - SCOPED_TRACE("CREATE audit entry for subnets"); - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::CREATE, "subnet set", - ServerSelector::ALL(), 3); - } - - // Deleting non-existing shared network should return 0. - EXPECT_EQ(0, cbptr_->deleteSharedNetwork6(ServerSelector::ALL(), "big-fish")); - // All shared networks should be still there. - ASSERT_EQ(test_networks_.size() - 1, networks.size()); - - // Should not delete the shared network for explicit server tag - // because our shared network is for all servers. - EXPECT_EQ(0, cbptr_->deleteSharedNetwork6(ServerSelector::ONE("server1"), - test_networks_[1]->getName())); - - // Same for all shared networks. - EXPECT_EQ(0, cbptr_->deleteAllSharedNetworks6(ServerSelector::ONE("server1"))); - - // Delete first shared network with it subnets and verify it is gone. - // Begin by its subnet. - EXPECT_EQ(1, cbptr_->deleteSharedNetworkSubnets6(ServerSelector::ANY(), - test_networks_[1]->getName())); - - { - SCOPED_TRACE("DELETE audit entry for subnets of the first shared network"); - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::DELETE, - "deleted all subnets for a shared network"); - } - - // Check that the subnet is gone.. - subnet = cbptr_->getSubnet6(ServerSelector::ALL(), test_subnets_[0]->getID()); - EXPECT_FALSE(subnet); - - // And after the shared network itself. - EXPECT_EQ(1, cbptr_->deleteSharedNetwork6(ServerSelector::ALL(), test_networks_[1]->getName())); - networks = cbptr_->getAllSharedNetworks6(ServerSelector::ALL()); - ASSERT_EQ(test_networks_.size() - 2, networks.size()); - - { - SCOPED_TRACE("DELETE audit entry for the first shared network"); - testNewAuditEntry("dhcp6_shared_network", AuditEntry::ModificationType::DELETE, - "shared network deleted"); - } - - // Delete all. - EXPECT_EQ(2, cbptr_->deleteAllSharedNetworks6(ServerSelector::ALL())); - networks = cbptr_->getAllSharedNetworks6(ServerSelector::ALL()); - ASSERT_TRUE(networks.empty()); - - { - SCOPED_TRACE("DELETE audit entry for the remaining two shared networks"); - // The last parameter indicates that we expect two new audit entries. - testNewAuditEntry("dhcp6_shared_network", AuditEntry::ModificationType::DELETE, - "deleted all shared networks", ServerSelector::ALL(), 2); - } - - // Check that subnets are still there but detached. - subnet = cbptr_->getSubnet6(ServerSelector::ALL(), test_subnets_[2]->getID()); - ASSERT_TRUE(subnet); - EXPECT_TRUE(subnet->getSharedNetworkName().empty()); - subnet = cbptr_->getSubnet6(ServerSelector::ALL(), test_subnets_[3]->getID()); - ASSERT_TRUE(subnet); - EXPECT_TRUE(subnet->getSharedNetworkName().empty()); -} - -// Test that getAllSharedNetworks6 throws appropriate exceptions for various -// server selectors. -TEST_F(PgSqlConfigBackendDHCPv6Test, getAllSharedNetworks6Selectors) { - // Supported selectors. - EXPECT_NO_THROW(cbptr_->getAllSharedNetworks6(ServerSelector::UNASSIGNED())); - EXPECT_NO_THROW(cbptr_->getAllSharedNetworks6(ServerSelector::ALL())); - EXPECT_NO_THROW(cbptr_->getAllSharedNetworks6(ServerSelector::ONE("server1"))); - EXPECT_NO_THROW( - cbptr_->getAllSharedNetworks6(ServerSelector::MULTIPLE({"server1", "server2"}))); - - // Not supported selectors. - EXPECT_THROW(cbptr_->getAllSharedNetworks6(ServerSelector::ANY()), isc::InvalidOperation); -} - -// Test that shared networks with different server associations are returned. -TEST_F(PgSqlConfigBackendDHCPv6Test, getAllSharedNetworks6WithServerTags) { - auto shared_network1 = test_networks_[0]; - auto shared_network2 = test_networks_[2]; - auto shared_network3 = test_networks_[3]; - - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[0])); - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[2])); - - EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), shared_network1)); - EXPECT_NO_THROW( - cbptr_->createUpdateSharedNetwork6(ServerSelector::ONE("server1"), shared_network2)); - EXPECT_NO_THROW( - cbptr_->createUpdateSharedNetwork6(ServerSelector::MULTIPLE({"server1", "server2"}), - shared_network3)); - - SharedNetwork6Collection networks; - - // All three networks are associated with the server1. - EXPECT_NO_THROW(networks = cbptr_->getAllSharedNetworks6(ServerSelector::ONE("server1"))); - EXPECT_EQ(3, networks.size()); - - // First network is associated with all servers. - auto returned_network = SharedNetworkFetcher6::get(networks, "level1"); - ASSERT_TRUE(returned_network); - EXPECT_TRUE(returned_network->hasAllServerTag()); - EXPECT_FALSE(returned_network->hasServerTag(ServerTag("server1"))); - EXPECT_FALSE(returned_network->hasServerTag(ServerTag("server2"))); - - // Second network is only associated with the server1. - returned_network = SharedNetworkFetcher6::get(networks, "level2"); - ASSERT_TRUE(returned_network); - EXPECT_FALSE(returned_network->hasAllServerTag()); - EXPECT_TRUE(returned_network->hasServerTag(ServerTag("server1"))); - EXPECT_FALSE(returned_network->hasServerTag(ServerTag("server2"))); - - // Third network is associated with both server1 and server2. - returned_network = SharedNetworkFetcher6::get(networks, "level3"); - ASSERT_TRUE(returned_network); - EXPECT_FALSE(returned_network->hasAllServerTag()); - EXPECT_TRUE(returned_network->hasServerTag(ServerTag("server1"))); - EXPECT_TRUE(returned_network->hasServerTag(ServerTag("server2"))); - - // For server2 we should only get two shared networks, i.e. first and last. - EXPECT_NO_THROW(networks = cbptr_->getAllSharedNetworks6(ServerSelector::ONE("server2"))); - EXPECT_EQ(2, networks.size()); - - // First shared network is associated with all servers. - returned_network = SharedNetworkFetcher6::get(networks, "level1"); - ASSERT_TRUE(returned_network); - EXPECT_TRUE(returned_network->hasAllServerTag()); - EXPECT_FALSE(returned_network->hasServerTag(ServerTag("server1"))); - EXPECT_FALSE(returned_network->hasServerTag(ServerTag("server2"))); - - // Last shared network is associated with server1 and server2. - returned_network = SharedNetworkFetcher6::get(networks, "level3"); - ASSERT_TRUE(returned_network); - EXPECT_FALSE(returned_network->hasAllServerTag()); - EXPECT_TRUE(returned_network->hasServerTag(ServerTag("server1"))); - EXPECT_TRUE(returned_network->hasServerTag(ServerTag("server2"))); - - // Only the first shared network is associated with all servers. - EXPECT_NO_THROW(networks = cbptr_->getAllSharedNetworks6(ServerSelector::ALL())); - EXPECT_EQ(1, networks.size()); - - returned_network = SharedNetworkFetcher6::get(networks, "level1"); - ASSERT_TRUE(returned_network); - EXPECT_TRUE(returned_network->hasAllServerTag()); - EXPECT_FALSE(returned_network->hasServerTag(ServerTag("server1"))); - EXPECT_FALSE(returned_network->hasServerTag(ServerTag("server2"))); -} - -// Test that shared networks modified after given time can be fetched. -TEST_F(PgSqlConfigBackendDHCPv6Test, getModifiedSharedNetworks6) { - // Explicitly set timestamps of shared networks. First shared - // network has a timestamp pointing to the future. Second shared - // network has timestamp pointing to the past (yesterday). - // Third shared network has a timestamp pointing to the - // past (an hour ago). - test_networks_[1]->setModificationTime(timestamps_["tomorrow"]); - test_networks_[2]->setModificationTime(timestamps_["yesterday"]); - test_networks_[3]->setModificationTime(timestamps_["today"]); - - // Insert shared networks into the database. - for (int i = 1; i < test_networks_.size(); ++i) { - cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), test_networks_[i]); - } - - // Fetch shared networks with timestamp later than today. Only one - // shared network should be returned. - SharedNetwork6Collection networks = - cbptr_->getModifiedSharedNetworks6(ServerSelector::ALL(), timestamps_["after today"]); - ASSERT_EQ(1, networks.size()); - - // Fetch shared networks with timestamp later than yesterday. We - // should get two shared networks. - networks = cbptr_->getModifiedSharedNetworks6(ServerSelector::ALL(), - timestamps_["after yesterday"]); - ASSERT_EQ(2, networks.size()); - - // Fetch shared networks with timestamp later than tomorrow. Nothing - // should be returned. - networks = cbptr_->getModifiedSharedNetworks6(ServerSelector::ALL(), - timestamps_["after tomorrow"]); - ASSERT_TRUE(networks.empty()); -} - -// Test that getModifiedSharedNetworks6 throws appropriate exceptions for various -// server selectors. -TEST_F(PgSqlConfigBackendDHCPv6Test, getModifiedSharedNetworks6Selectors) { - // Supported selectors. - EXPECT_NO_THROW( - cbptr_->getModifiedSharedNetworks6(ServerSelector::UNASSIGNED(), timestamps_["yesterday"])); - EXPECT_NO_THROW( - cbptr_->getModifiedSharedNetworks6(ServerSelector::ALL(), timestamps_["yesterday"])); - EXPECT_NO_THROW(cbptr_->getModifiedSharedNetworks6(ServerSelector::ONE("server1"), - timestamps_["yesterday"])); - EXPECT_NO_THROW( - cbptr_->getModifiedSharedNetworks6(ServerSelector::MULTIPLE({"server1", "server2"}), - timestamps_["yesterday"])); - - // Not supported selectors. - EXPECT_THROW(cbptr_->getModifiedSharedNetworks6(ServerSelector::ANY(), - timestamps_["yesterday"]), - isc::InvalidOperation); -} - -// Test that selected shared network can be deleted. -TEST_F(PgSqlConfigBackendDHCPv6Test, deleteSharedNetwork6) { - // Create two servers in the database. - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[0])); - { - SCOPED_TRACE("CREATE audit entry for server"); - testNewAuditEntry("dhcp6_server", AuditEntry::ModificationType::CREATE, "server set"); - } - - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[2])); - { - SCOPED_TRACE("CREATE audit entry for server"); - testNewAuditEntry("dhcp6_server", AuditEntry::ModificationType::CREATE, "server set"); - } - - auto shared_network1 = test_networks_[0]; - auto shared_network2 = test_networks_[2]; - auto shared_network3 = test_networks_[3]; - - // Insert two shared networks, one for all servers, and one for server2. - EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), shared_network1)); - EXPECT_NO_THROW( - cbptr_->createUpdateSharedNetwork6(ServerSelector::ONE("server2"), shared_network2)); - EXPECT_NO_THROW( - cbptr_->createUpdateSharedNetwork6(ServerSelector::MULTIPLE({"server1", "server2"}), - shared_network3)); - - auto test_no_delete = [this](const std::string& test_case_name, - const ServerSelector& server_selector, - const SharedNetwork6Ptr& shared_network) { - SCOPED_TRACE(test_case_name); - uint64_t deleted_count = 0; - EXPECT_NO_THROW(deleted_count = cbptr_->deleteSharedNetwork6(server_selector, - shared_network->getName())); - EXPECT_EQ(0, deleted_count); - }; - - { - SCOPED_TRACE("Test valid but non matching server selectors"); - test_no_delete("selector: one, actual: all", ServerSelector::ONE("server2"), - shared_network1); - test_no_delete("selector: all, actual: one", ServerSelector::ALL(), shared_network2); - test_no_delete("selector: all, actual: multiple", ServerSelector::ALL(), shared_network3); - } - - // We are not going to support deletion of a single entry for multiple servers. - EXPECT_THROW(cbptr_->deleteSharedNetwork6(ServerSelector::MULTIPLE({"server1", "server2"}), - shared_network3->getName()), - isc::InvalidOperation); - - // We currently don't support deleting a shared network with specifying - // an unassigned server tag. Use ANY to delete any subnet instead. - EXPECT_THROW(cbptr_->deleteSharedNetwork6(ServerSelector::UNASSIGNED(), - shared_network1->getName()), - isc::NotImplemented); - - // Test successful deletion of a shared network. - auto test_delete = [this](const std::string& test_case_name, - const ServerSelector& server_selector, - const SharedNetwork6Ptr& shared_network) { - SCOPED_TRACE(test_case_name); - uint64_t deleted_count = 0; - EXPECT_NO_THROW(deleted_count = cbptr_->deleteSharedNetwork6(server_selector, - shared_network->getName())); - EXPECT_EQ(1, deleted_count); - - EXPECT_FALSE(cbptr_->getSharedNetwork6(server_selector, shared_network->getName())); - }; - - test_delete("all servers", ServerSelector::ALL(), shared_network1); - test_delete("any server", ServerSelector::ANY(), shared_network2); - test_delete("one server", ServerSelector::ONE("server1"), shared_network3); -} - -// Test that deleteSharedNetwork6 throws appropriate exceptions for various -// server selectors. -TEST_F(PgSqlConfigBackendDHCPv6Test, deleteSharedNetwork6Selectors) { - // Supported selectors. - EXPECT_NO_THROW(cbptr_->deleteSharedNetwork6(ServerSelector::ANY(), "level1")); - EXPECT_NO_THROW(cbptr_->deleteSharedNetwork6(ServerSelector::ALL(), "level1")); - EXPECT_NO_THROW(cbptr_->deleteSharedNetwork6(ServerSelector::ONE("server1"), "level1")); - - // Not supported selectors. - EXPECT_THROW(cbptr_->deleteSharedNetwork6(ServerSelector::MULTIPLE({"server1", "server2"}), - "level1"), - isc::InvalidOperation); - - // Not implemented selectors. - EXPECT_THROW(cbptr_->deleteSharedNetwork6(ServerSelector::UNASSIGNED(), "level1"), - isc::NotImplemented); -} - -// Test that deleteAllSharedNetworks6 throws appropriate exceptions for various -// server selectors. -TEST_F(PgSqlConfigBackendDHCPv6Test, deleteAllSharedNetworks6Selectors) { - // Supported selectors. - EXPECT_NO_THROW(cbptr_->deleteAllSharedNetworks6(ServerSelector::UNASSIGNED())); - EXPECT_NO_THROW(cbptr_->deleteAllSharedNetworks6(ServerSelector::ALL())); - EXPECT_NO_THROW(cbptr_->deleteAllSharedNetworks6(ServerSelector::ONE("server1"))); - - // Not supported selectors. - EXPECT_THROW(cbptr_->deleteAllSharedNetworks6(ServerSelector::ANY()), isc::InvalidOperation); - EXPECT_THROW(cbptr_->deleteAllSharedNetworks6(ServerSelector::MULTIPLE({"server1", "server2"})), - isc::InvalidOperation); -} - -// Test that it is possible to retrieve and delete orphaned shared network. -TEST_F(PgSqlConfigBackendDHCPv6Test, unassignedSharedNetwork) { - // Create the server. - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[0])); - - // Create the shared networks and associate them with the server1. - auto shared_network = test_networks_[0]; - auto shared_network2 = test_networks_[2]; - EXPECT_NO_THROW( - cbptr_->createUpdateSharedNetwork6(ServerSelector::ONE("server1"), shared_network)); - EXPECT_NO_THROW( - cbptr_->createUpdateSharedNetwork6(ServerSelector::ONE("server1"), shared_network2)); - - // Delete the server. The shared networks should be preserved but are - // considered orphaned, i.e. do not belong to any server. - uint64_t deleted_count = 0; - EXPECT_NO_THROW(deleted_count = cbptr_->deleteServer6(ServerTag("server1"))); - EXPECT_EQ(1, deleted_count); - - // Trying to fetch this shared network by server tag should return no result. - SharedNetwork6Ptr returned_network; - EXPECT_NO_THROW( - returned_network = cbptr_->getSharedNetwork6(ServerSelector::ONE("server1"), "level1")); - EXPECT_FALSE(returned_network); - - // The same if we use other calls. - SharedNetwork6Collection returned_networks; - EXPECT_NO_THROW( - returned_networks = cbptr_->getAllSharedNetworks6(ServerSelector::ONE("server1"))); - EXPECT_TRUE(returned_networks.empty()); - - EXPECT_NO_THROW( - returned_networks = cbptr_->getModifiedSharedNetworks6(ServerSelector::ONE("server1"), - timestamps_["two days ago"])); - EXPECT_TRUE(returned_networks.empty()); - - // We should get the shared network if we ask for unassigned. - EXPECT_NO_THROW( - returned_network = cbptr_->getSharedNetwork6(ServerSelector::UNASSIGNED(), "level1")); - ASSERT_TRUE(returned_network); - - // Also if we ask for all unassigned networks it should be returned. - EXPECT_NO_THROW( - returned_networks = cbptr_->getAllSharedNetworks6(ServerSelector::UNASSIGNED())); - ASSERT_EQ(2, returned_networks.size()); - - // And all modified. - EXPECT_NO_THROW( - returned_networks = cbptr_->getModifiedSharedNetworks6(ServerSelector::UNASSIGNED(), - timestamps_["two days ago"])); - ASSERT_EQ(2, returned_networks.size()); - - // If we ask for any network by name, it should be returned too. - EXPECT_NO_THROW(returned_network = cbptr_->getSharedNetwork6(ServerSelector::ANY(), "level1")); - ASSERT_TRUE(returned_network); - - // Deleting a shared network with the mismatched server tag should not affect - // our shared network. - EXPECT_NO_THROW( - deleted_count = cbptr_->deleteSharedNetwork6(ServerSelector::ONE("server1"), "level1")); - EXPECT_EQ(0, deleted_count); - - // Also, if we delete all shared networks for server1. - EXPECT_NO_THROW( - deleted_count = cbptr_->deleteAllSharedNetworks6(ServerSelector::ONE("server1"))); - EXPECT_EQ(0, deleted_count); - - // We can delete this shared network when we specify ANY and the matching name. - EXPECT_NO_THROW(deleted_count = cbptr_->deleteSharedNetwork6(ServerSelector::ANY(), "level1")); - EXPECT_EQ(1, deleted_count); - - // We can delete all second networks using UNASSIGNED selector. - EXPECT_NO_THROW( - deleted_count = cbptr_->deleteAllSharedNetworks6(ServerSelector::UNASSIGNED());); - EXPECT_EQ(1, deleted_count); -} - -// Test that lifetimes in shared networks are handled as expected. -TEST_F(PgSqlConfigBackendDHCPv6Test, sharedNetworkLifetime) { - // Insert new shared network with unspecified valid lifetime - SharedNetwork6Ptr network(new SharedNetwork6("foo")); - Triplet unspecified; - network->setPreferred(unspecified); - network->setValid(unspecified); - network->setIface("eth1"); - cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), network); - - // Fetch this shared network. - SharedNetwork6Ptr returned_network = cbptr_->getSharedNetwork6(ServerSelector::ALL(), "foo"); - ASSERT_TRUE(returned_network); - - // Verified returned and original shared networks match. - EXPECT_EQ(network->toElement()->str(), returned_network->toElement()->str()); - - // Update the preferred and valid lifetime. - network->setPreferred(Triplet(100, 200, 300)); - network->setValid(Triplet(200, 300, 400)); - cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), network); - - // Fetch and verify again. - returned_network = cbptr_->getSharedNetwork6(ServerSelector::ALL(), "foo"); - ASSERT_TRUE(returned_network); - EXPECT_EQ(network->toElement()->str(), returned_network->toElement()->str()); -} - -// Test that deleting a shared network triggers deletion of the options -// associated with the shared network. -TEST_F(PgSqlConfigBackendDHCPv6Test, sharedNetworkOptions) { - // Add shared network with three options. - EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), test_networks_[0])); - EXPECT_EQ(3, countRows("dhcp6_options")); - - // Add another shared network with a single option. The numnber of options in the - // database should now be 4. - EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), test_networks_[2])); - EXPECT_EQ(4, countRows("dhcp6_options")); - - // The second shared network uses the same name as the first shared network, so - // this operation should replace the existing shared network and its options. - EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), test_networks_[1])); - EXPECT_EQ(1, countRows("dhcp6_options")); - - // Remove the shared network. This should not affect options assigned to the - // other shared network. - EXPECT_NO_THROW( - cbptr_->deleteSharedNetwork6(ServerSelector::ALL(), test_networks_[1]->getName())); - EXPECT_EQ(1, countRows("dhcp6_shared_network")); - EXPECT_EQ(1, countRows("dhcp6_options")); - - // Create the first option again. The number of options should be equal to the - // sum of options associated with both shared networks. - EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), test_networks_[0])); - EXPECT_EQ(4, countRows("dhcp6_options")); - - // Delete this shared network. This should not affect the option associated - // with the remaining shared network. - EXPECT_NO_THROW( - cbptr_->deleteSharedNetwork6(ServerSelector::ALL(), test_networks_[0]->getName())); - EXPECT_EQ(1, countRows("dhcp6_shared_network")); - EXPECT_EQ(1, countRows("dhcp6_options")); -} - -// Test that option definition can be inserted, fetched, updated and then -// fetched again. -TEST_F(PgSqlConfigBackendDHCPv6Test, getOptionDef6) { - // Insert new option definition. - OptionDefinitionPtr option_def = test_option_defs_[0]; - cbptr_->createUpdateOptionDef6(ServerSelector::ALL(), option_def); - - // Fetch this option_definition by subnet identifier. - OptionDefinitionPtr returned_option_def = - cbptr_->getOptionDef6(ServerSelector::ALL(), test_option_defs_[0]->getCode(), - test_option_defs_[0]->getOptionSpaceName()); - ASSERT_TRUE(returned_option_def); - EXPECT_GT(returned_option_def->getId(), 0); - ASSERT_EQ(1, returned_option_def->getServerTags().size()); - EXPECT_EQ("all", returned_option_def->getServerTags().begin()->get()); - - EXPECT_TRUE(returned_option_def->equals(*option_def)); - - { - SCOPED_TRACE("CREATE audit entry for an option definition"); - testNewAuditEntry("dhcp6_option_def", AuditEntry::ModificationType::CREATE, - "option definition set"); - } - - // Update the option definition in the database. - OptionDefinitionPtr option_def2 = test_option_defs_[1]; - cbptr_->createUpdateOptionDef6(ServerSelector::ALL(), option_def2); - - // Fetch updated option definition and see if it matches. - returned_option_def = cbptr_->getOptionDef6(ServerSelector::ALL(), - test_option_defs_[1]->getCode(), - test_option_defs_[1]->getOptionSpaceName()); - EXPECT_TRUE(returned_option_def->equals(*option_def2)); - - // Fetching option definition for an explicitly specified server tag - // should succeed too. - returned_option_def = cbptr_->getOptionDef6(ServerSelector::ONE("server1"), - test_option_defs_[1]->getCode(), - test_option_defs_[1]->getOptionSpaceName()); - EXPECT_TRUE(returned_option_def->equals(*option_def2)); - - { - SCOPED_TRACE("UPDATE audit entry for an option definition"); - testNewAuditEntry("dhcp6_option_def", AuditEntry::ModificationType::UPDATE, - "option definition set"); - } -} - -// This test verifies that it is possible to differentiate between the -// option definitions by server tag and that the option definition -// specified for the particular server overrides the definition for -// all servers. -TEST_F(PgSqlConfigBackendDHCPv6Test, optionDefs6WithServerTags) { - OptionDefinitionPtr option1 = test_option_defs_[0]; - OptionDefinitionPtr option2 = test_option_defs_[1]; - OptionDefinitionPtr option3 = test_option_defs_[4]; - - // An attempt to create option definition for non-existing server should - // fail. - EXPECT_THROW(cbptr_->createUpdateOptionDef6(ServerSelector::ONE("server1"), option1), - NullKeyError); - - // Create two servers. - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[1])); - { - SCOPED_TRACE("server1 is created"); - testNewAuditEntry("dhcp6_server", AuditEntry::ModificationType::CREATE, "server set"); - } - - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[2])); - { - SCOPED_TRACE("server2 is created"); - testNewAuditEntry("dhcp6_server", AuditEntry::ModificationType::CREATE, "server set"); - } - - // This time creation of the option definition for the server1 should pass. - EXPECT_NO_THROW(cbptr_->createUpdateOptionDef6(ServerSelector::ONE("server1"), option1)); - { - SCOPED_TRACE("option definition for server1 is set"); - // The value of 3 means there should be 3 audit entries available for the - // server1, two that indicate creation of the servers and one that we - // validate, which sets the option definition. - testNewAuditEntry("dhcp6_option_def", AuditEntry::ModificationType::CREATE, - "option definition set", ServerSelector::ONE("server1"), 3, 1); - } - - // Creation of the option definition for the server2 should also pass. - EXPECT_NO_THROW(cbptr_->createUpdateOptionDef6(ServerSelector::ONE("server2"), option2)); - { - SCOPED_TRACE("option definition for server2 is set"); - // Same as in case of the server1, there should be 3 audit entries and - // we validate one of them. - testNewAuditEntry("dhcp6_option_def", AuditEntry::ModificationType::CREATE, - "option definition set", ServerSelector::ONE("server2"), 3, 1); - } - - // Finally, creation of the option definition for all servers should - // also pass. - EXPECT_NO_THROW(cbptr_->createUpdateOptionDef6(ServerSelector::ALL(), option3)); - { - SCOPED_TRACE("option definition for server2 is set"); - // There should be one new audit entry for all servers. It logs - // the insertion of the option definition. - testNewAuditEntry("dhcp6_option_def", AuditEntry::ModificationType::CREATE, - "option definition set", ServerSelector::ALL(), 1, 1); - } - - OptionDefinitionPtr returned_option_def; - - // Try to fetch the option definition specified for all servers. It should - // return the third one. - EXPECT_NO_THROW(returned_option_def = cbptr_->getOptionDef6(ServerSelector::ALL(), - option3->getCode(), - option3->getOptionSpaceName())); - ASSERT_TRUE(returned_option_def); - EXPECT_TRUE(returned_option_def->equals(*option3)); - - // Try to fetch the option definition specified for server1. It should - // override the definition for all servers. - EXPECT_NO_THROW(returned_option_def = cbptr_->getOptionDef6(ServerSelector::ONE("server1"), - option1->getCode(), - option1->getOptionSpaceName())); - ASSERT_TRUE(returned_option_def); - EXPECT_TRUE(returned_option_def->equals(*option1)); - - // The same in case of the server2. - EXPECT_NO_THROW(returned_option_def = cbptr_->getOptionDef6(ServerSelector::ONE("server2"), - option2->getCode(), - option2->getOptionSpaceName())); - ASSERT_TRUE(returned_option_def); - EXPECT_TRUE(returned_option_def->equals(*option2)); - - OptionDefContainer returned_option_defs; - - // Try to fetch the collection of the option definitions for server1, server2 - // and server3. The server3 does not have an explicit option definition, so - // for this server we should get the definition associated with "all" servers. - EXPECT_NO_THROW(returned_option_defs = cbptr_->getAllOptionDefs6( - ServerSelector::MULTIPLE({"server1", "server2", "server3"}));); - ASSERT_EQ(3, returned_option_defs.size()); - - // Check that expected option definitions have been returned. - auto current_option = returned_option_defs.begin(); - EXPECT_TRUE((*current_option)->equals(*option1)); - EXPECT_TRUE((*(++current_option))->equals(*option2)); - EXPECT_TRUE((*(++current_option))->equals(*option3)); - - // Try to fetch the collection of options specified for all servers. - // This excludes the options specific to server1 and server2. It returns - // only the common ones. - EXPECT_NO_THROW(returned_option_defs = cbptr_->getAllOptionDefs6(ServerSelector::ALL()); - - ); - ASSERT_EQ(1, returned_option_defs.size()); - EXPECT_TRUE((*returned_option_defs.begin())->equals(*option3)); - - // Delete the server1. It should remove associations of this server with the - // option definitions and the option definition itself. - EXPECT_NO_THROW(cbptr_->deleteServer6(ServerTag("server1"))); - EXPECT_NO_THROW( - returned_option_defs = cbptr_->getAllOptionDefs6(ServerSelector::ONE("server1")); - - ); - ASSERT_EQ(1, returned_option_defs.size()); - EXPECT_TRUE((*returned_option_defs.begin())->equals(*option3)); - - { - SCOPED_TRACE("DELETE audit entry for the option definition after server deletion"); - testNewAuditEntry("dhcp6_option_def", AuditEntry::ModificationType::DELETE, - "deleting a server", ServerSelector::ONE("server1"), 2, 1); - } - - // Attempt to delete option definition for server1. - uint64_t deleted_num = 0; - EXPECT_NO_THROW(deleted_num = cbptr_->deleteOptionDef6(ServerSelector::ONE("server1"), - option1->getCode(), - option1->getOptionSpaceName())); - EXPECT_EQ(0, deleted_num); - - // Deleting the existing option definition for server2 should succeed. - EXPECT_NO_THROW(deleted_num = cbptr_->deleteOptionDef6(ServerSelector::ONE("server2"), - option2->getCode(), - option2->getOptionSpaceName())); - EXPECT_EQ(1, deleted_num); - - // Create this option definition again to test that deletion of all servers - // removes it too. - EXPECT_NO_THROW(cbptr_->createUpdateOptionDef6(ServerSelector::ONE("server2"), option2)); - - // Delete all servers, except 'all'. - EXPECT_NO_THROW(deleted_num = cbptr_->deleteAllServers6()); - EXPECT_NO_THROW(returned_option_defs = cbptr_->getAllOptionDefs6(ServerSelector::ALL());); - EXPECT_EQ(1, deleted_num); - EXPECT_EQ(1, returned_option_defs.size()); - EXPECT_TRUE((*returned_option_defs.begin())->equals(*option3)); - - { - SCOPED_TRACE("DELETE audit entry for the option definition after deletion of" - " all servers"); - testNewAuditEntry("dhcp6_option_def", AuditEntry::ModificationType::DELETE, - "deleting all servers", ServerSelector::ONE("server2"), 4, 1); - } -} - -// Test that all option definitions can be fetched. -TEST_F(PgSqlConfigBackendDHCPv6Test, getAllOptionDefs6) { - // Insert test option definitions into the database. Note that the second - // option definition will overwrite the first option definition as they use - // the same code and space. - size_t updates_num = 0; - for (auto option_def : test_option_defs_) { - cbptr_->createUpdateOptionDef6(ServerSelector::ALL(), option_def); - - // That option definition overrides the first one so the audit entry should - // indicate an update. - if (option_def->getName() == "bar") { - SCOPED_TRACE("UPDATE audit entry for the option definition " + option_def->getName()); - testNewAuditEntry("dhcp6_option_def", AuditEntry::ModificationType::UPDATE, - "option definition set"); - ++updates_num; - - } else { - SCOPED_TRACE("CREATE audit entry for the option definition " + option_def->getName()); - testNewAuditEntry("dhcp6_option_def", AuditEntry::ModificationType::CREATE, - "option definition set"); - } - } - - // Fetch all option_definitions. - OptionDefContainer option_defs = cbptr_->getAllOptionDefs6(ServerSelector::ALL()); - ASSERT_EQ(test_option_defs_.size() - updates_num, option_defs.size()); - - // All option definitions should also be returned for explicitly specified - // server tag. - option_defs = cbptr_->getAllOptionDefs6(ServerSelector::ONE("server1")); - ASSERT_EQ(test_option_defs_.size() - updates_num, option_defs.size()); - - // See if option definitions are returned ok. - for (auto def = option_defs.begin(); def != option_defs.end(); ++def) { - ASSERT_EQ(1, (*def)->getServerTags().size()); - EXPECT_EQ("all", (*def)->getServerTags().begin()->get()); - bool success = false; - for (auto i = 1; i < test_option_defs_.size(); ++i) { - if ((*def)->equals(*test_option_defs_[i])) { - success = true; - } - } - ASSERT_TRUE(success) << "failed for option definition " << (*def)->getCode() - << ", option space " << (*def)->getOptionSpaceName(); - } - - // Deleting non-existing option definition should return 0. - EXPECT_EQ(0, cbptr_->deleteOptionDef6(ServerSelector::ALL(), 99, "non-exiting-space")); - // All option definitions should be still there. - ASSERT_EQ(test_option_defs_.size() - updates_num, option_defs.size()); - - // Should not delete option definition for explicit server tag - // because our option definition is for all servers. - EXPECT_EQ(0, cbptr_->deleteOptionDef6(ServerSelector::ONE("server1"), - test_option_defs_[1]->getCode(), - test_option_defs_[1]->getOptionSpaceName())); - - // Same for all option definitions. - EXPECT_EQ(0, cbptr_->deleteAllOptionDefs6(ServerSelector::ONE("server1"))); - - // Delete one of the option definitions and see if it is gone. - EXPECT_EQ(1, cbptr_->deleteOptionDef6(ServerSelector::ALL(), test_option_defs_[2]->getCode(), - test_option_defs_[2]->getOptionSpaceName())); - ASSERT_FALSE(cbptr_->getOptionDef6(ServerSelector::ALL(), test_option_defs_[2]->getCode(), - test_option_defs_[2]->getOptionSpaceName())); - - { - SCOPED_TRACE("DELETE audit entry for the first option definition"); - testNewAuditEntry("dhcp6_option_def", AuditEntry::ModificationType::DELETE, - "option definition deleted"); - } - - // Delete all remaining option definitions. - EXPECT_EQ(2, cbptr_->deleteAllOptionDefs6(ServerSelector::ALL())); - option_defs = cbptr_->getAllOptionDefs6(ServerSelector::ALL()); - ASSERT_TRUE(option_defs.empty()); - - { - SCOPED_TRACE("DELETE audit entries for the remaining option definitions"); - // The last parameter indicates that we expect two new audit entries. - testNewAuditEntry("dhcp6_option_def", AuditEntry::ModificationType::DELETE, - "deleted all option definitions", ServerSelector::ALL(), 2); - } -} - -// Test that option definitions modified after given time can be fetched. -TEST_F(PgSqlConfigBackendDHCPv6Test, getModifiedOptionDefs6) { - // Explicitly set timestamps of option definitions. First option - // definition has a timestamp pointing to the future. Second option - // definition has timestamp pointing to the past (yesterday). - // Third option definitions has a timestamp pointing to the - // past (an hour ago). - test_option_defs_[1]->setModificationTime(timestamps_["tomorrow"]); - test_option_defs_[2]->setModificationTime(timestamps_["yesterday"]); - test_option_defs_[3]->setModificationTime(timestamps_["today"]); - - // Insert option definitions into the database. - for (int i = 1; i < test_networks_.size(); ++i) { - cbptr_->createUpdateOptionDef6(ServerSelector::ALL(), test_option_defs_[i]); - } - - // Fetch option definitions with timestamp later than today. Only one - // option definition should be returned. - OptionDefContainer option_defs = cbptr_->getModifiedOptionDefs6(ServerSelector::ALL(), - timestamps_["after today"]); - ASSERT_EQ(1, option_defs.size()); - - // Fetch option definitions with timestamp later than yesterday. We - // should get two option definitions. - option_defs = cbptr_->getModifiedOptionDefs6(ServerSelector::ALL(), - timestamps_["after yesterday"]); - ASSERT_EQ(2, option_defs.size()); - - // Fetch option definitions with timestamp later than tomorrow. Nothing - // should be returned. - option_defs = cbptr_->getModifiedOptionDefs6(ServerSelector::ALL(), - timestamps_["after tomorrow"]); - ASSERT_TRUE(option_defs.empty()); -} - -// This test verifies that global option can be added, updated and deleted. -TEST_F(PgSqlConfigBackendDHCPv6Test, createUpdateDeleteOption6) { - // Add option to the database. - OptionDescriptorPtr opt_posix_timezone = test_options_[0]; - cbptr_->createUpdateOption6(ServerSelector::ALL(), opt_posix_timezone); - - // Make sure we can retrieve this option and that it is equal to the - // option we have inserted into the database. - OptionDescriptorPtr returned_opt_posix_timezone = - cbptr_->getOption6(ServerSelector::ALL(), opt_posix_timezone->option_->getType(), - opt_posix_timezone->space_name_); - ASSERT_TRUE(returned_opt_posix_timezone); - - { - SCOPED_TRACE("verify created option"); - testOptionsEquivalent(*opt_posix_timezone, *returned_opt_posix_timezone); - } - - { - SCOPED_TRACE("CREATE audit entry for an option"); - testNewAuditEntry("dhcp6_options", AuditEntry::ModificationType::CREATE, - "global option set"); - } - - // Modify option and update it in the database. - opt_posix_timezone->persistent_ = !opt_posix_timezone->persistent_; - cbptr_->createUpdateOption6(ServerSelector::ALL(), opt_posix_timezone); - - // Retrieve the option again and make sure that updates were - // properly propagated to the database. Use explicit server selector - // which should also return this option. - returned_opt_posix_timezone = cbptr_->getOption6(ServerSelector::ONE("server1"), - opt_posix_timezone->option_->getType(), - opt_posix_timezone->space_name_); - ASSERT_TRUE(returned_opt_posix_timezone); - - { - SCOPED_TRACE("verify updated option"); - testOptionsEquivalent(*opt_posix_timezone, *returned_opt_posix_timezone); - } - - { - SCOPED_TRACE("UPDATE audit entry for an option"); - testNewAuditEntry("dhcp6_options", AuditEntry::ModificationType::UPDATE, - "global option set"); - } - - // Deleting an option with explicitly specified server tag should fail. - EXPECT_EQ(0, cbptr_->deleteOption6(ServerSelector::ONE("server1"), - opt_posix_timezone->option_->getType(), - opt_posix_timezone->space_name_)); - - // Deleting option for all servers should succeed. - EXPECT_EQ(1, - cbptr_->deleteOption6(ServerSelector::ALL(), opt_posix_timezone->option_->getType(), - opt_posix_timezone->space_name_)); - - EXPECT_FALSE(cbptr_->getOption6(ServerSelector::ALL(), opt_posix_timezone->option_->getType(), - opt_posix_timezone->space_name_)); - - { - SCOPED_TRACE("DELETE audit entry for an option"); - testNewAuditEntry("dhcp6_options", AuditEntry::ModificationType::DELETE, - "global option deleted"); - } -} - -// This test verifies that it is possible to differentiate between the -// global options by server tag and that the option specified for the -// particular server overrides the value specified for all servers. -TEST_F(PgSqlConfigBackendDHCPv6Test, globalOptions6WithServerTags) { - OptionDescriptorPtr opt_timezone1 = test_options_[0]; - OptionDescriptorPtr opt_timezone2 = test_options_[6]; - OptionDescriptorPtr opt_timezone3 = test_options_[7]; - - EXPECT_THROW(cbptr_->createUpdateOption6(ServerSelector::ONE("server1"), opt_timezone1), - NullKeyError); - - // Create two servers. - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[1])); - { - SCOPED_TRACE("server1 is created"); - testNewAuditEntry("dhcp6_server", AuditEntry::ModificationType::CREATE, "server set"); - } - - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[2])); - { - SCOPED_TRACE("server2 is created"); - testNewAuditEntry("dhcp6_server", AuditEntry::ModificationType::CREATE, "server set"); - } - - EXPECT_NO_THROW(cbptr_->createUpdateOption6(ServerSelector::ONE("server1"), opt_timezone1)); - { - SCOPED_TRACE("global option for server1 is set"); - // The value of 3 means there should be 3 audit entries available for the - // server1, two that indicate creation of the servers and one that we - // validate, which sets the global option. - testNewAuditEntry("dhcp6_options", AuditEntry::ModificationType::CREATE, - "global option set", ServerSelector::ONE("server1"), 3, 1); - } - - EXPECT_NO_THROW(cbptr_->createUpdateOption6(ServerSelector::ONE("server2"), opt_timezone2)); - { - SCOPED_TRACE("global option for server2 is set"); - // Same as in case of the server1, there should be 3 audit entries and - // we validate one of them. - testNewAuditEntry("dhcp6_options", AuditEntry::ModificationType::CREATE, - "global option set", ServerSelector::ONE("server2"), 3, 1); - } - - EXPECT_NO_THROW(cbptr_->createUpdateOption6(ServerSelector::ALL(), opt_timezone3)); - { - SCOPED_TRACE("global option for all servers is set"); - // There should be one new audit entry for all servers. It logs - // the insertion of the global option. - testNewAuditEntry("dhcp6_options", AuditEntry::ModificationType::CREATE, - "global option set", ServerSelector::ALL(), 1, 1); - } - - OptionDescriptorPtr returned_option; - - // Try to fetch the option specified for all servers. It should return - // the third option. - EXPECT_NO_THROW(returned_option = cbptr_->getOption6(ServerSelector::ALL(), - opt_timezone3->option_->getType(), - opt_timezone3->space_name_);); - ASSERT_TRUE(returned_option); - testOptionsEquivalent(*opt_timezone3, *returned_option); - - // Try to fetch the option specified for the server1. It should override the - // option specified for all servers. - EXPECT_NO_THROW(returned_option = cbptr_->getOption6(ServerSelector::ONE("server1"), - opt_timezone1->option_->getType(), - opt_timezone1->space_name_);); - ASSERT_TRUE(returned_option); - testOptionsEquivalent(*opt_timezone1, *returned_option); - - // The same in case of the server2. - EXPECT_NO_THROW(returned_option = cbptr_->getOption6(ServerSelector::ONE("server2"), - opt_timezone2->option_->getType(), - opt_timezone2->space_name_);); - ASSERT_TRUE(returned_option); - testOptionsEquivalent(*opt_timezone2, *returned_option); - - OptionContainer returned_options; - - // Try to fetch the collection of global options for the server1, server2 - // and server3. The server3 does not have an explicit value so for this server - // we should get the option associated with "all" servers. - EXPECT_NO_THROW(returned_options = cbptr_->getAllOptions6( - ServerSelector::MULTIPLE({"server1", "server2", "server3"}));); - ASSERT_EQ(3, returned_options.size()); - - // Check that expected options have been returned. - auto current_option = returned_options.begin(); - testOptionsEquivalent(*opt_timezone1, *current_option); - testOptionsEquivalent(*opt_timezone2, *(++current_option)); - testOptionsEquivalent(*opt_timezone3, *(++current_option)); - - // Try to fetch the collection of options specified for all servers. - // This excludes the options specific to server1 and server2. It returns - // only the common ones. - EXPECT_NO_THROW(returned_options = cbptr_->getAllOptions6(ServerSelector::ALL());); - ASSERT_EQ(1, returned_options.size()); - testOptionsEquivalent(*opt_timezone3, *returned_options.begin()); - - // Delete the server1. It should remove associations of this server with the - // option and the option itself. - EXPECT_NO_THROW(cbptr_->deleteServer6(ServerTag("server1"))); - EXPECT_NO_THROW(returned_options = cbptr_->getAllOptions6(ServerSelector::ONE("server1"));); - ASSERT_EQ(1, returned_options.size()); - testOptionsEquivalent(*opt_timezone3, *returned_options.begin()); - - { - SCOPED_TRACE("DELETE audit entry for the global option after server deletion"); - testNewAuditEntry("dhcp6_options", AuditEntry::ModificationType::DELETE, - "deleting a server", ServerSelector::ONE("server1"), 2, 1); - } - - // Attempt to delete global option for server1. - uint64_t deleted_num = 0; - EXPECT_NO_THROW(deleted_num = cbptr_->deleteOption6(ServerSelector::ONE("server1"), - opt_timezone1->option_->getType(), - opt_timezone1->space_name_)); - EXPECT_EQ(0, deleted_num); - - // Deleting the existing option for server2 should succeed. - EXPECT_NO_THROW(deleted_num = cbptr_->deleteOption6(ServerSelector::ONE("server2"), - opt_timezone2->option_->getType(), - opt_timezone2->space_name_)); - EXPECT_EQ(1, deleted_num); - - // Create this option again to test that deletion of all servers removes it too. - EXPECT_NO_THROW(cbptr_->createUpdateOption6(ServerSelector::ONE("server2"), opt_timezone2)); - - // Delete all servers, except 'all'. - EXPECT_NO_THROW(deleted_num = cbptr_->deleteAllServers6()); - EXPECT_NO_THROW(returned_options = cbptr_->getAllOptions6(ServerSelector::ALL());); - EXPECT_EQ(1, deleted_num); - ASSERT_EQ(1, returned_options.size()); - testOptionsEquivalent(*opt_timezone3, *returned_options.begin()); - - { - SCOPED_TRACE("DELETE audit entry for the global option after deletion of" - " all servers"); - testNewAuditEntry("dhcp6_options", AuditEntry::ModificationType::DELETE, - "deleting all servers", ServerSelector::ONE("server2"), 4, 1); - } -} - -// This test verifies that all global options can be retrieved. -TEST_F(PgSqlConfigBackendDHCPv6Test, getAllOptions6) { - // Add three global options to the database. - cbptr_->createUpdateOption6(ServerSelector::ALL(), test_options_[0]); - cbptr_->createUpdateOption6(ServerSelector::ALL(), test_options_[1]); - cbptr_->createUpdateOption6(ServerSelector::ALL(), test_options_[5]); - - // Retrieve all these options. - OptionContainer returned_options = cbptr_->getAllOptions6(ServerSelector::ALL()); - ASSERT_EQ(3, returned_options.size()); - - // Fetching global options with explicitly specified server tag should return - // the same result. - returned_options = cbptr_->getAllOptions6(ServerSelector::ONE("server1")); - ASSERT_EQ(3, returned_options.size()); - - // Get the container index used to search options by option code. - const OptionContainerTypeIndex& index = returned_options.get<1>(); - - // Verify that all options we put into the database were - // returned. - { - SCOPED_TRACE("verify test_options_[0]"); - auto option0 = index.find(test_options_[0]->option_->getType()); - ASSERT_FALSE(option0 == index.end()); - testOptionsEquivalent(*test_options_[0], *option0); - EXPECT_GT(option0->getId(), 0); - ASSERT_EQ(1, option0->getServerTags().size()); - EXPECT_EQ("all", option0->getServerTags().begin()->get()); - } - - { - SCOPED_TRACE("verify test_options_[1]"); - auto option1 = index.find(test_options_[1]->option_->getType()); - ASSERT_FALSE(option1 == index.end()); - testOptionsEquivalent(*test_options_[1], *option1); - EXPECT_GT(option1->getId(), 0); - ASSERT_EQ(1, option1->getServerTags().size()); - EXPECT_EQ("all", option1->getServerTags().begin()->get()); - } - - { - SCOPED_TRACE("verify test_options_[5]"); - auto option5 = index.find(test_options_[5]->option_->getType()); - ASSERT_FALSE(option5 == index.end()); - testOptionsEquivalent(*test_options_[5], *option5); - EXPECT_GT(option5->getId(), 0); - ASSERT_EQ(1, option5->getServerTags().size()); - EXPECT_EQ("all", option5->getServerTags().begin()->get()); - } -} - -// This test verifies that modified global options can be retrieved. -TEST_F(PgSqlConfigBackendDHCPv6Test, getModifiedOptions6) { - // Assign timestamps to the options we're going to store in the - // database. - test_options_[0]->setModificationTime(timestamps_["tomorrow"]); - test_options_[1]->setModificationTime(timestamps_["yesterday"]); - test_options_[5]->setModificationTime(timestamps_["today"]); - - // Put options into the database. - cbptr_->createUpdateOption6(ServerSelector::ALL(), test_options_[0]); - cbptr_->createUpdateOption6(ServerSelector::ALL(), test_options_[1]); - cbptr_->createUpdateOption6(ServerSelector::ALL(), test_options_[5]); - - // Get options with the timestamp later than today. Only - // one option should be returned. - OptionContainer returned_options = cbptr_->getModifiedOptions6(ServerSelector::ALL(), - timestamps_["after today"]); - ASSERT_EQ(1, returned_options.size()); - - // Fetching modified options with explicitly specified server selector - // should return the same result. - returned_options = cbptr_->getModifiedOptions6(ServerSelector::ONE("server1"), - timestamps_["after today"]); - ASSERT_EQ(1, returned_options.size()); - - // The returned option should be the one with the timestamp - // set to tomorrow. - const OptionContainerTypeIndex& index = returned_options.get<1>(); - auto option0 = index.find(test_options_[0]->option_->getType()); - ASSERT_FALSE(option0 == index.end()); - { - SCOPED_TRACE("verify returned option"); - testOptionsEquivalent(*test_options_[0], *option0); - } -} - -// This test verifies that subnet level option can be added, updated and -// deleted. -TEST_F(PgSqlConfigBackendDHCPv6Test, createUpdateDeleteSubnetOption6) { - // Insert new subnet. - Subnet6Ptr subnet = test_subnets_[1]; - cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet); - - // Fetch this subnet by subnet identifier. - Subnet6Ptr returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(), subnet->getID()); - ASSERT_TRUE(returned_subnet); - - { - SCOPED_TRACE("CREATE audit entry for a new subnet"); - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::CREATE, "subnet set"); - } - - // The inserted subnet contains four options. - ASSERT_EQ(4, countRows("dhcp6_options")); - - OptionDescriptorPtr opt_posix_timezone = test_options_[0]; - cbptr_->createUpdateOption6(ServerSelector::ANY(), subnet->getID(), opt_posix_timezone); - - returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(), subnet->getID()); - ASSERT_TRUE(returned_subnet); - - OptionDescriptor returned_opt_posix_timezone = - returned_subnet->getCfgOption()->get(DHCP6_OPTION_SPACE, D6O_NEW_POSIX_TIMEZONE); - ASSERT_TRUE(returned_opt_posix_timezone.option_); - - { - SCOPED_TRACE("verify returned option"); - testOptionsEquivalent(*opt_posix_timezone, returned_opt_posix_timezone); - EXPECT_GT(returned_opt_posix_timezone.getId(), 0); - } - - { - SCOPED_TRACE("UPDATE audit entry for an added subnet option"); - // Instead of adding an audit entry for an option we add an audit - // entry for the entire subnet so as the server refreshes the - // subnet with the new option. Note that the server doesn't - // have means to retrieve only the newly added option. - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::UPDATE, - "subnet specific option set"); - } - - // We have added one option to the existing subnet. We should now have - // five options. - ASSERT_EQ(5, countRows("dhcp6_options")); - - opt_posix_timezone->persistent_ = !opt_posix_timezone->persistent_; - cbptr_->createUpdateOption6(ServerSelector::ANY(), subnet->getID(), opt_posix_timezone); - - returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(), subnet->getID()); - ASSERT_TRUE(returned_subnet); - returned_opt_posix_timezone = returned_subnet->getCfgOption()->get(DHCP6_OPTION_SPACE, - D6O_NEW_POSIX_TIMEZONE); - ASSERT_TRUE(returned_opt_posix_timezone.option_); - - { - SCOPED_TRACE("verify returned option with modified persistence"); - testOptionsEquivalent(*opt_posix_timezone, returned_opt_posix_timezone); - } - - { - SCOPED_TRACE("UPDATE audit entry for an updated subnet option"); - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::UPDATE, - "subnet specific option set"); - } - - // Updating the option should replace the existing instance with the new - // instance. Therefore, we should still have five options. - ASSERT_EQ(5, countRows("dhcp6_options")); - - // It should succeed for any server. - EXPECT_EQ(1, cbptr_->deleteOption6(ServerSelector::ANY(), subnet->getID(), - opt_posix_timezone->option_->getType(), - opt_posix_timezone->space_name_)); - - returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(), subnet->getID()); - ASSERT_TRUE(returned_subnet); - - EXPECT_FALSE( - returned_subnet->getCfgOption()->get(DHCP6_OPTION_SPACE, D6O_NEW_POSIX_TIMEZONE).option_); - - { - SCOPED_TRACE("UPDATE audit entry for a deleted subnet option"); - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::UPDATE, - "subnet specific option deleted"); - } - - // We should have only four options after deleting one of them. - ASSERT_EQ(4, countRows("dhcp6_options")); -} - -// This test verifies that option can be inserted, updated and deleted -// from the pool. -TEST_F(PgSqlConfigBackendDHCPv6Test, createUpdateDeletePoolOption6) { - // Insert new subnet. - Subnet6Ptr subnet = test_subnets_[1]; - cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet); - - { - SCOPED_TRACE("CREATE audit entry for a subnet"); - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::CREATE, "subnet set"); - } - - // Inserted subnet has four options. - ASSERT_EQ(4, countRows("dhcp6_options")); - - // Add an option into the pool. - const PoolPtr pool = subnet->getPool(Lease::TYPE_NA, IOAddress("2001:db8::10")); - ASSERT_TRUE(pool); - OptionDescriptorPtr opt_posix_timezone = test_options_[0]; - cbptr_->createUpdateOption6(ServerSelector::ANY(), pool->getFirstAddress(), - pool->getLastAddress(), opt_posix_timezone); - - // Query for a subnet. - Subnet6Ptr returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(), subnet->getID()); - ASSERT_TRUE(returned_subnet); - - // The returned subnet should include our pool. - const PoolPtr returned_pool = returned_subnet->getPool(Lease::TYPE_NA, - IOAddress("2001:db8::10")); - ASSERT_TRUE(returned_pool); - - // The pool should contain option we added earlier. - OptionDescriptor returned_opt_posix_timezone = - returned_pool->getCfgOption()->get(DHCP6_OPTION_SPACE, D6O_NEW_POSIX_TIMEZONE); - ASSERT_TRUE(returned_opt_posix_timezone.option_); - - { - SCOPED_TRACE("verify returned pool option"); - testOptionsEquivalent(*opt_posix_timezone, returned_opt_posix_timezone); - EXPECT_GT(returned_opt_posix_timezone.getId(), 0); - } - - { - SCOPED_TRACE("UPDATE audit entry for a subnet after adding an option " - "to the address pool"); - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::UPDATE, - "address pool specific option set"); - } - - // With the newly inserted option we should now have five options. - ASSERT_EQ(5, countRows("dhcp6_options")); - - // Modify the option and update it in the database. - opt_posix_timezone->persistent_ = !opt_posix_timezone->persistent_; - cbptr_->createUpdateOption6(ServerSelector::ANY(), pool->getFirstAddress(), - pool->getLastAddress(), opt_posix_timezone); - - // Fetch the subnet and the corresponding pool. - returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(), subnet->getID()); - ASSERT_TRUE(returned_subnet); - const PoolPtr returned_pool1 = returned_subnet->getPool(Lease::TYPE_NA, - IOAddress("2001:db8::10")); - ASSERT_TRUE(returned_pool1); - - // Test that the option has been correctly updated in the database. - returned_opt_posix_timezone = returned_pool1->getCfgOption()->get(DHCP6_OPTION_SPACE, - D6O_NEW_POSIX_TIMEZONE); - ASSERT_TRUE(returned_opt_posix_timezone.option_); - - { - SCOPED_TRACE("verify updated option with modified persistence"); - testOptionsEquivalent(*opt_posix_timezone, returned_opt_posix_timezone); - } - - { - SCOPED_TRACE("UPDATE audit entry for a subnet when updating " - "address pool specific option"); - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::UPDATE, - "address pool specific option set"); - } - - // The new option instance should replace the existing one, so we should - // still have five options. - ASSERT_EQ(5, countRows("dhcp6_options")); - - // Delete option for any server should succeed. - EXPECT_EQ(1, - cbptr_->deleteOption6(ServerSelector::ANY(), pool->getFirstAddress(), - pool->getLastAddress(), opt_posix_timezone->option_->getType(), - opt_posix_timezone->space_name_)); - - // Fetch the subnet and the pool from the database again to make sure - // that the option is really gone. - returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(), subnet->getID()); - ASSERT_TRUE(returned_subnet); - const PoolPtr returned_pool2 = returned_subnet->getPool(Lease::TYPE_NA, - IOAddress("2001:db8::10")); - ASSERT_TRUE(returned_pool2); - - // Option should be gone. - EXPECT_FALSE( - returned_pool2->getCfgOption()->get(DHCP6_OPTION_SPACE, D6O_NEW_POSIX_TIMEZONE).option_); - - { - SCOPED_TRACE("UPDATE audit entry for a subnet when deleting " - "address pool specific option"); - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::UPDATE, - "address pool specific option deleted"); - } - - // The option has been deleted so the number of options should now - // be down to 4. - EXPECT_EQ(4, countRows("dhcp6_options")); -} - -// This test verifies that option can be inserted, updated and deleted -// from the pd pool. -TEST_F(PgSqlConfigBackendDHCPv6Test, createUpdateDeletePdPoolOption6) { - // Insert new subnet. - Subnet6Ptr subnet = test_subnets_[1]; - cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet); - - { - SCOPED_TRACE("CREATE audit entry for a subnet"); - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::CREATE, "subnet set"); - } - - // Inserted subnet has four options. - ASSERT_EQ(4, countRows("dhcp6_options")); - - // Add an option into the pd pool. - const PoolPtr pd_pool = subnet->getPool(Lease::TYPE_PD, IOAddress("2001:db8:a:10::")); - ASSERT_TRUE(pd_pool); - OptionDescriptorPtr opt_posix_timezone = test_options_[0]; - int pd_pool_len = prefixLengthFromRange(pd_pool->getFirstAddress(), pd_pool->getLastAddress()); - cbptr_->createUpdateOption6(ServerSelector::ANY(), pd_pool->getFirstAddress(), - static_cast(pd_pool_len), opt_posix_timezone); - - // Query for a subnet. - Subnet6Ptr returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(), subnet->getID()); - ASSERT_TRUE(returned_subnet); - - // The returned subnet should include our pool. - const PoolPtr returned_pd_pool = returned_subnet->getPool(Lease::TYPE_PD, - IOAddress("2001:db8:a:10::")); - ASSERT_TRUE(returned_pd_pool); - - // The pd pool should contain option we added earlier. - OptionDescriptor returned_opt_posix_timezone = - returned_pd_pool->getCfgOption()->get(DHCP6_OPTION_SPACE, D6O_NEW_POSIX_TIMEZONE); - ASSERT_TRUE(returned_opt_posix_timezone.option_); - - { - SCOPED_TRACE("verify returned pool option"); - testOptionsEquivalent(*opt_posix_timezone, returned_opt_posix_timezone); - EXPECT_GT(returned_opt_posix_timezone.getId(), 0); - } - - { - SCOPED_TRACE("UPDATE audit entry for a subnet after adding an option " - "to the prefix delegation pool"); - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::UPDATE, - "prefix delegation pool specific option set"); - } - - // With the newly inserted option we should now have five options. - ASSERT_EQ(5, countRows("dhcp6_options")); - - // Modify the option and update it in the database. - opt_posix_timezone->persistent_ = !opt_posix_timezone->persistent_; - cbptr_->createUpdateOption6(ServerSelector::ANY(), pd_pool->getFirstAddress(), - static_cast(pd_pool_len), opt_posix_timezone); - - // Fetch the subnet and the corresponding pd pool. - returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(), subnet->getID()); - ASSERT_TRUE(returned_subnet); - const PoolPtr returned_pd_pool1 = returned_subnet->getPool(Lease::TYPE_PD, - IOAddress("2001:db8:a:10::")); - ASSERT_TRUE(returned_pd_pool1); - - // Test that the option has been correctly updated in the database. - returned_opt_posix_timezone = returned_pd_pool1->getCfgOption()->get(DHCP6_OPTION_SPACE, - D6O_NEW_POSIX_TIMEZONE); - ASSERT_TRUE(returned_opt_posix_timezone.option_); - - { - SCOPED_TRACE("verify updated option with modified persistence"); - testOptionsEquivalent(*opt_posix_timezone, returned_opt_posix_timezone); - } - - { - SCOPED_TRACE("UPDATE audit entry for a subnet when updating " - "prefix delegation pool specific option"); - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::UPDATE, - "prefix delegation pool specific option set"); - } - - // The new option instance should replace the existing one, so we should - // still have five options. - ASSERT_EQ(5, countRows("dhcp6_options")); - - // Delete option for any server should succeed. - EXPECT_EQ(1, cbptr_->deleteOption6(ServerSelector::ANY(), pd_pool->getFirstAddress(), - static_cast(pd_pool_len), - opt_posix_timezone->option_->getType(), - opt_posix_timezone->space_name_)); - - // Fetch the subnet and the pool from the database again to make sure - // that the option is really gone. - returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(), subnet->getID()); - ASSERT_TRUE(returned_subnet); - const PoolPtr returned_pd_pool2 = returned_subnet->getPool(Lease::TYPE_PD, - IOAddress("2001:db8:a:10::")); - ASSERT_TRUE(returned_pd_pool2); - - // Option should be gone. - EXPECT_FALSE( - returned_pd_pool2->getCfgOption()->get(DHCP6_OPTION_SPACE, D6O_NEW_POSIX_TIMEZONE).option_); - - { - SCOPED_TRACE("UPDATE audit entry for a subnet when deleting " - "prefix delegation pool specific option"); - testNewAuditEntry("dhcp6_subnet", AuditEntry::ModificationType::UPDATE, - "prefix delegation pool specific option deleted"); - } - - // The option has been deleted so the number of options should now - // be down to 4. - EXPECT_EQ(4, countRows("dhcp6_options")); -} - -// This test verifies that shared network level option can be added, -// updated and deleted. -TEST_F(PgSqlConfigBackendDHCPv6Test, createUpdateDeleteSharedNetworkOption6) { - // Insert new shared network. - SharedNetwork6Ptr shared_network = test_networks_[1]; - cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), shared_network); - - // Fetch this shared network by name. - SharedNetwork6Ptr returned_network = cbptr_->getSharedNetwork6(ServerSelector::ALL(), - shared_network->getName()); - ASSERT_TRUE(returned_network); - - { - SCOPED_TRACE("CREATE audit entry for the new shared network"); - testNewAuditEntry("dhcp6_shared_network", AuditEntry::ModificationType::CREATE, - "shared network set"); - } - - // The inserted shared network has no options. - ASSERT_EQ(0, countRows("dhcp6_options")); - - OptionDescriptorPtr opt_posix_timezone = test_options_[0]; - cbptr_->createUpdateOption6(ServerSelector::ANY(), shared_network->getName(), - opt_posix_timezone); - - returned_network = cbptr_->getSharedNetwork6(ServerSelector::ALL(), shared_network->getName()); - ASSERT_TRUE(returned_network); - - OptionDescriptor returned_opt_posix_timezone = - returned_network->getCfgOption()->get(DHCP6_OPTION_SPACE, D6O_NEW_POSIX_TIMEZONE); - ASSERT_TRUE(returned_opt_posix_timezone.option_); - - { - SCOPED_TRACE("verify returned option"); - testOptionsEquivalent(*opt_posix_timezone, returned_opt_posix_timezone); - EXPECT_GT(returned_opt_posix_timezone.getId(), 0); - } - - { - SCOPED_TRACE("UPDATE audit entry for the added shared network option"); - // Instead of adding an audit entry for an option we add an audit - // entry for the entire shared network so as the server refreshes the - // shared network with the new option. Note that the server doesn't - // have means to retrieve only the newly added option. - testNewAuditEntry("dhcp6_shared_network", AuditEntry::ModificationType::UPDATE, - "shared network specific option set"); - } - - // One option should now be stored in the database. - ASSERT_EQ(1, countRows("dhcp6_options")); - - opt_posix_timezone->persistent_ = !opt_posix_timezone->persistent_; - cbptr_->createUpdateOption6(ServerSelector::ANY(), shared_network->getName(), - opt_posix_timezone); - - returned_network = cbptr_->getSharedNetwork6(ServerSelector::ALL(), shared_network->getName()); - ASSERT_TRUE(returned_network); - returned_opt_posix_timezone = returned_network->getCfgOption()->get(DHCP6_OPTION_SPACE, - D6O_NEW_POSIX_TIMEZONE); - ASSERT_TRUE(returned_opt_posix_timezone.option_); - - { - SCOPED_TRACE("verify updated option with modified persistence"); - testOptionsEquivalent(*opt_posix_timezone, returned_opt_posix_timezone); - } - - { - SCOPED_TRACE("UPDATE audit entry for the updated shared network option"); - testNewAuditEntry("dhcp6_shared_network", AuditEntry::ModificationType::UPDATE, - "shared network specific option set"); - } - - // The new option instance should replace the existing option instance, - // so we should still have one option. - ASSERT_EQ(1, countRows("dhcp6_options")); - - // Deleting an option for any server should succeed. - EXPECT_EQ(1, cbptr_->deleteOption6(ServerSelector::ANY(), shared_network->getName(), - opt_posix_timezone->option_->getType(), - opt_posix_timezone->space_name_)); - returned_network = cbptr_->getSharedNetwork6(ServerSelector::ALL(), shared_network->getName()); - ASSERT_TRUE(returned_network); - EXPECT_FALSE( - returned_network->getCfgOption()->get(DHCP6_OPTION_SPACE, D6O_NEW_POSIX_TIMEZONE).option_); - - { - SCOPED_TRACE("UPDATE audit entry for the deleted shared network option"); - testNewAuditEntry("dhcp6_shared_network", AuditEntry::ModificationType::UPDATE, - "shared network specific option deleted"); - } - - // After deleting the option we should be back to 0. - EXPECT_EQ(0, countRows("dhcp6_options")); -} - -// This test verifies that option id values in one subnet do -// not impact options returned in subsequent subnets when -// fetching subnets from the backend. -TEST_F(PgSqlConfigBackendDHCPv6Test, subnetOptionIdOrder) { - - // Add a network with two pools with two options each. - EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ALL(), test_subnets_[1])); - EXPECT_EQ(2, countRows("dhcp6_pool")); - EXPECT_EQ(4, countRows("dhcp6_options")); - - // Add second subnet with a single option. The number of options in the database - // should now be 3. - EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ALL(), test_subnets_[2])); - EXPECT_EQ(2, countRows("dhcp6_pool")); - EXPECT_EQ(5, countRows("dhcp6_options")); - - // Now replace the first subnet with three options and two pools. This will cause - // the option id values for this subnet to be larger than those in the second - // subnet. - EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ALL(), test_subnets_[0])); - EXPECT_EQ(2, countRows("dhcp6_pool")); - EXPECT_EQ(4, countRows("dhcp6_options")); - - // Now fetch all subnets. - Subnet6Collection subnets; - EXPECT_NO_THROW(subnets = cbptr_->getAllSubnets6(ServerSelector::ALL())); - ASSERT_EQ(2, subnets.size()); - - // Verify that the subnets returned are as expected. - for (auto subnet : subnets) { - ASSERT_EQ(1, subnet->getServerTags().size()); - EXPECT_EQ("all", subnet->getServerTags().begin()->get()); - if (subnet->getID() == 1024) { - EXPECT_EQ(test_subnets_[0]->toElement()->str(), subnet->toElement()->str()); - } else if (subnet->getID() == 2048) { - EXPECT_EQ(test_subnets_[2]->toElement()->str(), subnet->toElement()->str()); - } else { - ADD_FAILURE() << "unexpected subnet id:" << subnet->getID(); - } - } -} - -// This test verifies that option id values in one shared network do -// not impact options returned in subsequent shared networks when -// fetching shared networks from the backend. -TEST_F(PgSqlConfigBackendDHCPv6Test, sharedNetworkOptionIdOrder) { - auto level1_options = test_networks_[0]; - auto level1_no_options = test_networks_[1]; - auto level2 = test_networks_[2]; - - // Insert two shared networks. We insert level1 without options first, - // then level2. - EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), level1_no_options)); - - EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), level2)); - // Fetch all shared networks. - SharedNetwork6Collection networks = cbptr_->getAllSharedNetworks6(ServerSelector::ALL()); - - ASSERT_EQ(2, networks.size()); - - // See if shared networks are returned ok. - for (auto i = 0; i < networks.size(); ++i) { - if (i == 0) { - // level1_no_options - EXPECT_EQ(level1_no_options->toElement()->str(), networks[i]->toElement()->str()); - } else { - // bar - EXPECT_EQ(level2->toElement()->str(), networks[i]->toElement()->str()); - } - } - - EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork6(ServerSelector::ALL(), level1_options)); - - // Fetch all shared networks. - networks = cbptr_->getAllSharedNetworks6(ServerSelector::ALL()); - ASSERT_EQ(2, networks.size()); - - // See if shared networks are returned ok. - for (auto i = 0; i < networks.size(); ++i) { - if (i == 0) { - // level1_no_options - EXPECT_EQ(level1_options->toElement()->str(), networks[i]->toElement()->str()); - } else { - // bar - EXPECT_EQ(level2->toElement()->str(), networks[i]->toElement()->str()); - } - } -} - -/// This test verifies that audit entries can be retrieved from a given -/// timestamp and id including when two entries can get the same timestamp. -/// (either it is a common even and this should catch it, or it is a rare -/// event and it does not matter). -TEST_F(PgSqlConfigBackendDHCPv6Test, multipleAuditEntries) { - // Get current time. - boost::posix_time::ptime now = boost::posix_time::second_clock::local_time(); - - // Create a server. - EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[1])); - - // Create a global parameter and update it many times. - const ServerSelector& server_selector = ServerSelector::ALL(); - StampedValuePtr param; - ElementPtr value; - for (int i = 0; i < 100; ++i) { - value = Element::create(i); - param = StampedValue::create("my-parameter", value); - cbptr_->createUpdateGlobalParameter6(server_selector, param); - } - - // Get all audit entries from now. - AuditEntryCollection audit_entries = cbptr_->getRecentAuditEntries(server_selector, now, 0); - - // Check that partial retrieves return the right count. - auto& mod_time_idx = audit_entries.get(); - for (auto it = mod_time_idx.begin(); it != mod_time_idx.end(); ++it) { - size_t partial_size = cbptr_ - ->getRecentAuditEntries(server_selector, - (*it)->getModificationTime(), - (*it)->getRevisionId()) - .size(); - EXPECT_EQ(partial_size + 1, std::distance(it, mod_time_idx.end())); - } -} - -class PgSqlConfigBackendDHCPv6DbLostCallbackTest : public ::testing::Test { -public: - PgSqlConfigBackendDHCPv6DbLostCallbackTest() - : db_lost_callback_called_(0), db_recovered_callback_called_(0), - db_failed_callback_called_(0), - io_service_(boost::make_shared()) { - isc::db::DatabaseConnection::db_lost_callback_ = 0; - isc::db::DatabaseConnection::db_recovered_callback_ = 0; - isc::db::DatabaseConnection::db_failed_callback_ = 0; - isc::dhcp::PgSqlConfigBackendImpl::setIOService(io_service_); - isc::dhcp::TimerMgr::instance()->setIOService(io_service_); - isc::dhcp::CfgMgr::instance().clear(); - } - - virtual ~PgSqlConfigBackendDHCPv6DbLostCallbackTest() { - isc::db::DatabaseConnection::db_lost_callback_ = 0; - isc::db::DatabaseConnection::db_recovered_callback_ = 0; - isc::db::DatabaseConnection::db_failed_callback_ = 0; - isc::dhcp::PgSqlConfigBackendImpl::setIOService(isc::asiolink::IOServicePtr()); - isc::dhcp::TimerMgr::instance()->unregisterTimers(); - isc::dhcp::CfgMgr::instance().clear(); - } - - /// @brief Prepares the class for a test. - /// - /// Invoked by gtest prior test entry, we create the - /// appropriate schema and create a basic DB manager to - /// wipe out any prior instance - virtual void SetUp() { - // Ensure we have the proper schema with no transient data. - createPgSQLSchema(); - isc::dhcp::CfgMgr::instance().clear(); - isc::dhcp::PgSqlConfigBackendDHCPv6::registerBackendType(); - } - - /// @brief Pre-text exit clean up - /// - /// Invoked by gtest upon test exit, we destroy the schema - /// we created. - virtual void TearDown() { - // If data wipe enabled, delete transient data otherwise destroy the schema - destroyPgSQLSchema(); - isc::dhcp::CfgMgr::instance().clear(); - isc::dhcp::PgSqlConfigBackendDHCPv6::unregisterBackendType(); - } - - /// @brief Method which returns the back end specific connection - /// string - virtual std::string validConnectString() { - return (validPgSQLConnectionString()); - } - - /// @brief Method which returns invalid back end specific connection - /// string - virtual std::string invalidConnectString() { - return (connectionString(PGSQL_VALID_TYPE, INVALID_NAME, VALID_HOST, VALID_USER, - VALID_PASSWORD)); - } - - /// @brief Verifies open failures do NOT invoke db lost callback - /// - /// The db lost callback should only be invoked after successfully - /// opening the DB and then subsequently losing it. Failing to - /// open should be handled directly by the application layer. - void testNoCallbackOnOpenFailure(); - - /// @brief Verifies the CB manager's behavior if DB connection is lost - /// - /// This function creates a CB manager with a back end that supports - /// connectivity lost callback. It verifies connectivity by issuing a known - /// valid query. Next it simulates connectivity lost by identifying and - /// closing the socket connection to the CB backend. It then reissues the - /// query and verifies that: - /// -# The Query throws DbOperationError (rather than exiting) - /// -# The registered DbLostCallback was invoked - /// -# The registered DbRecoveredCallback was invoked - void testDbLostAndRecoveredCallback(); - - /// @brief Verifies the CB manager's behavior if DB connection is lost - /// - /// This function creates a CB manager with a back end that supports - /// connectivity lost callback. It verifies connectivity by issuing a known - /// valid query. Next it simulates connectivity lost by identifying and - /// closing the socket connection to the CB backend. It then reissues the - /// query and verifies that: - /// -# The Query throws DbOperationError (rather than exiting) - /// -# The registered DbLostCallback was invoked - /// -# The registered DbFailedCallback was invoked - void testDbLostAndFailedCallback(); - - /// @brief Verifies the CB manager's behavior if DB connection is lost - /// - /// This function creates a CB manager with a back end that supports - /// connectivity lost callback. It verifies connectivity by issuing a known - /// valid query. Next it simulates connectivity lost by identifying and - /// closing the socket connection to the CB backend. It then reissues the - /// query and verifies that: - /// -# The Query throws DbOperationError (rather than exiting) - /// -# The registered DbLostCallback was invoked - /// -# The registered DbRecoveredCallback was invoked after two reconnect - /// attempts (once failing and second triggered by timer) - void testDbLostAndRecoveredAfterTimeoutCallback(); - - /// @brief Verifies the CB manager's behavior if DB connection is lost - /// - /// This function creates a CB manager with a back end that supports - /// connectivity lost callback. It verifies connectivity by issuing a known - /// valid query. Next it simulates connectivity lost by identifying and - /// closing the socket connection to the CB backend. It then reissues the - /// query and verifies that: - /// -# The Query throws DbOperationError (rather than exiting) - /// -# The registered DbLostCallback was invoked - /// -# The registered DbFailedCallback was invoked after two reconnect - /// attempts (once failing and second triggered by timer) - void testDbLostAndFailedAfterTimeoutCallback(); - - /// @brief Callback function registered with the CB manager - bool db_lost_callback(db::ReconnectCtlPtr /* not_used */) { - return (++db_lost_callback_called_); - } - - /// @brief Flag used to detect calls to db_lost_callback function - uint32_t db_lost_callback_called_; - - /// @brief Callback function registered with the CB manager - bool db_recovered_callback(db::ReconnectCtlPtr /* not_used */) { - return (++db_recovered_callback_called_); - } - - /// @brief Flag used to detect calls to db_recovered_callback function - uint32_t db_recovered_callback_called_; - - /// @brief Callback function registered with the CB manager - bool db_failed_callback(db::ReconnectCtlPtr /* not_used */) { - return (++db_failed_callback_called_); - } - - /// @brief Flag used to detect calls to db_failed_callback function - uint32_t db_failed_callback_called_; - - /// The IOService object, used for all ASIO operations. - isc::asiolink::IOServicePtr io_service_; -}; - -void -PgSqlConfigBackendDHCPv6DbLostCallbackTest::testNoCallbackOnOpenFailure() { - isc::db::DatabaseConnection::db_lost_callback_ = - std::bind(&PgSqlConfigBackendDHCPv6DbLostCallbackTest::db_lost_callback, this, ph::_1); - - // Set the connectivity recovered callback. - isc::db::DatabaseConnection::db_recovered_callback_ = - std::bind(&PgSqlConfigBackendDHCPv6DbLostCallbackTest::db_recovered_callback, this, ph::_1); - - // Set the connectivity failed callback. - isc::db::DatabaseConnection::db_failed_callback_ = - std::bind(&PgSqlConfigBackendDHCPv6DbLostCallbackTest::db_failed_callback, this, ph::_1); - - std::string access = invalidConnectString(); - - // Connect to the CB backend. - ASSERT_THROW(ConfigBackendDHCPv6Mgr::instance().addBackend(access), DbOpenError); - - io_service_->poll(); - - EXPECT_EQ(0, db_lost_callback_called_); - EXPECT_EQ(0, db_recovered_callback_called_); - EXPECT_EQ(0, db_failed_callback_called_); -} - -void -PgSqlConfigBackendDHCPv6DbLostCallbackTest::testDbLostAndRecoveredCallback() { - // Set the connectivity lost callback. - isc::db::DatabaseConnection::db_lost_callback_ = - std::bind(&PgSqlConfigBackendDHCPv6DbLostCallbackTest::db_lost_callback, this, ph::_1); - - // Set the connectivity recovered callback. - isc::db::DatabaseConnection::db_recovered_callback_ = - std::bind(&PgSqlConfigBackendDHCPv6DbLostCallbackTest::db_recovered_callback, this, ph::_1); - - // Set the connectivity failed callback. - isc::db::DatabaseConnection::db_failed_callback_ = - std::bind(&PgSqlConfigBackendDHCPv6DbLostCallbackTest::db_failed_callback, this, ph::_1); - - std::string access = validConnectString(); - - ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo()); - config_ctl_info->addConfigDatabase(access); - CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info); - - // Find the most recently opened socket. Our SQL client's socket should - // be the next one. - int last_open_socket = findLastSocketFd(); - - // Fill holes. - FillFdHoles holes(last_open_socket); - - // Connect to the CB backend. - ASSERT_NO_THROW(ConfigBackendDHCPv6Mgr::instance().addBackend(access)); - - // Find the SQL client socket. - int sql_socket = findLastSocketFd(); - ASSERT_TRUE(sql_socket > last_open_socket); - - // Verify we can execute a query. We don't care about the answer. - ServerCollection servers; - ASSERT_NO_THROW( - servers = ConfigBackendDHCPv6Mgr::instance().getPool()->getAllServers6(BackendSelector())); - - // Now close the sql socket out from under backend client - ASSERT_EQ(0, close(sql_socket)); - - // A query should fail with DbConnectionUnusable. - ASSERT_THROW(servers = ConfigBackendDHCPv6Mgr::instance().getPool()->getAllServers6( - BackendSelector()), - DbConnectionUnusable); - - io_service_->poll(); - - // Our lost and recovered connectivity callback should have been invoked. - EXPECT_EQ(1, db_lost_callback_called_); - EXPECT_EQ(1, db_recovered_callback_called_); - EXPECT_EQ(0, db_failed_callback_called_); -} - -void -PgSqlConfigBackendDHCPv6DbLostCallbackTest::testDbLostAndFailedCallback() { - // Set the connectivity lost callback. - isc::db::DatabaseConnection::db_lost_callback_ = - std::bind(&PgSqlConfigBackendDHCPv6DbLostCallbackTest::db_lost_callback, this, ph::_1); - - // Set the connectivity recovered callback. - isc::db::DatabaseConnection::db_recovered_callback_ = - std::bind(&PgSqlConfigBackendDHCPv6DbLostCallbackTest::db_recovered_callback, this, ph::_1); - - // Set the connectivity failed callback. - isc::db::DatabaseConnection::db_failed_callback_ = - std::bind(&PgSqlConfigBackendDHCPv6DbLostCallbackTest::db_failed_callback, this, ph::_1); - - std::string access = validConnectString(); - ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo()); - config_ctl_info->addConfigDatabase(access); - CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info); - - // Find the most recently opened socket. Our SQL client's socket should - // be the next one. - int last_open_socket = findLastSocketFd(); - - // Fill holes. - FillFdHoles holes(last_open_socket); - - // Connect to the CB backend. - ASSERT_NO_THROW(ConfigBackendDHCPv6Mgr::instance().addBackend(access)); - - // Find the SQL client socket. - int sql_socket = findLastSocketFd(); - ASSERT_TRUE(sql_socket > last_open_socket); - - // Verify we can execute a query. We don't care about the answer. - ServerCollection servers; - ASSERT_NO_THROW( - servers = ConfigBackendDHCPv6Mgr::instance().getPool()->getAllServers6(BackendSelector())); - - access = invalidConnectString(); - CfgMgr::instance().clear(); - // by adding an invalid access will cause the manager factory to throw - // resulting in failure to recreate the manager - config_ctl_info.reset(new ConfigControlInfo()); - config_ctl_info->addConfigDatabase(access); - CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info); - const ConfigDbInfoList& cfg = - CfgMgr::instance().getCurrentCfg()->getConfigControlInfo()->getConfigDatabases(); - (const_cast(cfg))[0].setAccessString(access, true); - - // Now close the sql socket out from under backend client - ASSERT_EQ(0, close(sql_socket)); - - // A query should fail with DbConnectionUnusable. - ASSERT_THROW(servers = ConfigBackendDHCPv6Mgr::instance().getPool()->getAllServers6( - BackendSelector()), - DbConnectionUnusable); - - io_service_->poll(); - - // Our lost and failed connectivity callback should have been invoked. - EXPECT_EQ(1, db_lost_callback_called_); - EXPECT_EQ(0, db_recovered_callback_called_); - EXPECT_EQ(1, db_failed_callback_called_); -} - -void -PgSqlConfigBackendDHCPv6DbLostCallbackTest::testDbLostAndRecoveredAfterTimeoutCallback() { - // Set the connectivity lost callback. - isc::db::DatabaseConnection::db_lost_callback_ = - std::bind(&PgSqlConfigBackendDHCPv6DbLostCallbackTest::db_lost_callback, this, ph::_1); - - // Set the connectivity recovered callback. - isc::db::DatabaseConnection::db_recovered_callback_ = - std::bind(&PgSqlConfigBackendDHCPv6DbLostCallbackTest::db_recovered_callback, this, ph::_1); - - // Set the connectivity failed callback. - isc::db::DatabaseConnection::db_failed_callback_ = - std::bind(&PgSqlConfigBackendDHCPv6DbLostCallbackTest::db_failed_callback, this, ph::_1); - - std::string access = validConnectString(); - std::string extra = " max-reconnect-tries=3 reconnect-wait-time=1"; - access += extra; - ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo()); - config_ctl_info->addConfigDatabase(access); - CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info); - - // Find the most recently opened socket. Our SQL client's socket should - // be the next one. - int last_open_socket = findLastSocketFd(); - - // Fill holes. - FillFdHoles holes(last_open_socket); - - // Connect to the CB backend. - ASSERT_NO_THROW(ConfigBackendDHCPv6Mgr::instance().addBackend(access)); - - // Find the SQL client socket. - int sql_socket = findLastSocketFd(); - ASSERT_TRUE(sql_socket > last_open_socket); - - // Verify we can execute a query. We don't care about the answer. - ServerCollection servers; - ASSERT_NO_THROW( - servers = ConfigBackendDHCPv6Mgr::instance().getPool()->getAllServers6(BackendSelector())); - - access = invalidConnectString(); - access += extra; - CfgMgr::instance().clear(); - // by adding an invalid access will cause the manager factory to throw - // resulting in failure to recreate the manager - config_ctl_info.reset(new ConfigControlInfo()); - config_ctl_info->addConfigDatabase(access); - CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info); - const ConfigDbInfoList& cfg = - CfgMgr::instance().getCurrentCfg()->getConfigControlInfo()->getConfigDatabases(); - (const_cast(cfg))[0].setAccessString(access, true); - - // Now close the sql socket out from under backend client - ASSERT_EQ(0, close(sql_socket)); - - // A query should fail with DbConnectionUnusable. - ASSERT_THROW(servers = ConfigBackendDHCPv6Mgr::instance().getPool()->getAllServers6( - BackendSelector()), - DbConnectionUnusable); - - io_service_->poll(); - - // Our lost connectivity callback should have been invoked. - EXPECT_EQ(1, db_lost_callback_called_); - EXPECT_EQ(0, db_recovered_callback_called_); - EXPECT_EQ(0, db_failed_callback_called_); - - access = validConnectString(); - access += extra; - CfgMgr::instance().clear(); - config_ctl_info.reset(new ConfigControlInfo()); - config_ctl_info->addConfigDatabase(access); - CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info); - - sleep(1); - - io_service_->poll(); - - // Our lost and recovered connectivity callback should have been invoked. - EXPECT_EQ(2, db_lost_callback_called_); - EXPECT_EQ(1, db_recovered_callback_called_); - EXPECT_EQ(0, db_failed_callback_called_); - - sleep(1); - - io_service_->poll(); - - // No callback should have been invoked. - EXPECT_EQ(2, db_lost_callback_called_); - EXPECT_EQ(1, db_recovered_callback_called_); - EXPECT_EQ(0, db_failed_callback_called_); -} - -void -PgSqlConfigBackendDHCPv6DbLostCallbackTest::testDbLostAndFailedAfterTimeoutCallback() { - // Set the connectivity lost callback. - isc::db::DatabaseConnection::db_lost_callback_ = - std::bind(&PgSqlConfigBackendDHCPv6DbLostCallbackTest::db_lost_callback, this, ph::_1); - - // Set the connectivity recovered callback. - isc::db::DatabaseConnection::db_recovered_callback_ = - std::bind(&PgSqlConfigBackendDHCPv6DbLostCallbackTest::db_recovered_callback, this, ph::_1); - - // Set the connectivity failed callback. - isc::db::DatabaseConnection::db_failed_callback_ = - std::bind(&PgSqlConfigBackendDHCPv6DbLostCallbackTest::db_failed_callback, this, ph::_1); - - std::string access = validConnectString(); - std::string extra = " max-reconnect-tries=3 reconnect-wait-time=1"; - access += extra; - ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo()); - config_ctl_info->addConfigDatabase(access); - CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info); - - // Find the most recently opened socket. Our SQL client's socket should - // be the next one. - int last_open_socket = findLastSocketFd(); - - // Fill holes. - FillFdHoles holes(last_open_socket); - - // Connect to the CB backend. - ASSERT_NO_THROW(ConfigBackendDHCPv6Mgr::instance().addBackend(access)); - - // Find the SQL client socket. - int sql_socket = findLastSocketFd(); - ASSERT_TRUE(sql_socket > last_open_socket); - - // Verify we can execute a query. We don't care about the answer. - ServerCollection servers; - ASSERT_NO_THROW( - servers = ConfigBackendDHCPv6Mgr::instance().getPool()->getAllServers6(BackendSelector())); - - access = invalidConnectString(); - access += extra; - CfgMgr::instance().clear(); - // by adding an invalid access will cause the manager factory to throw - // resulting in failure to recreate the manager - config_ctl_info.reset(new ConfigControlInfo()); - config_ctl_info->addConfigDatabase(access); - CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info); - const ConfigDbInfoList& cfg = - CfgMgr::instance().getCurrentCfg()->getConfigControlInfo()->getConfigDatabases(); - (const_cast(cfg))[0].setAccessString(access, true); - - // Now close the sql socket out from under backend client - ASSERT_EQ(0, close(sql_socket)); - - // A query should fail with DbConnectionUnusable. - ASSERT_THROW(servers = ConfigBackendDHCPv6Mgr::instance().getPool()->getAllServers6( - BackendSelector()), - DbConnectionUnusable); - - io_service_->poll(); - - // Our lost connectivity callback should have been invoked. - EXPECT_EQ(1, db_lost_callback_called_); - EXPECT_EQ(0, db_recovered_callback_called_); - EXPECT_EQ(0, db_failed_callback_called_); - - sleep(1); - - io_service_->poll(); - - // Our lost connectivity callback should have been invoked. - EXPECT_EQ(2, db_lost_callback_called_); - EXPECT_EQ(0, db_recovered_callback_called_); - EXPECT_EQ(0, db_failed_callback_called_); - - sleep(1); - - io_service_->poll(); - - // Our lost and failed connectivity callback should have been invoked. - EXPECT_EQ(3, db_lost_callback_called_); - EXPECT_EQ(0, db_recovered_callback_called_); - EXPECT_EQ(1, db_failed_callback_called_); -} - -/// @brief Verifies that db lost callback is not invoked on an open failure -TEST_F(PgSqlConfigBackendDHCPv6DbLostCallbackTest, testNoCallbackOnOpenFailure) { - MultiThreadingTest mt(false); - testNoCallbackOnOpenFailure(); -} - -/// @brief Verifies that db lost callback is not invoked on an open failure -TEST_F(PgSqlConfigBackendDHCPv6DbLostCallbackTest, testNoCallbackOnOpenFailureMultiThreading) { - MultiThreadingTest mt(true); - testNoCallbackOnOpenFailure(); -} - -/// @brief Verifies that loss of connectivity to Postgres is handled correctly. -TEST_F(PgSqlConfigBackendDHCPv6DbLostCallbackTest, testDbLostAndRecoveredCallback) { - MultiThreadingTest mt(false); - testDbLostAndRecoveredCallback(); -} - -/// @brief Verifies that loss of connectivity to Postgres is handled correctly. -TEST_F(PgSqlConfigBackendDHCPv6DbLostCallbackTest, testDbLostAndRecoveredCallbackMultiThreading) { - MultiThreadingTest mt(true); - testDbLostAndRecoveredCallback(); -} - -/// @brief Verifies that loss of connectivity to Postgres is handled correctly. -TEST_F(PgSqlConfigBackendDHCPv6DbLostCallbackTest, testDbLostAndFailedCallback) { - MultiThreadingTest mt(false); - testDbLostAndFailedCallback(); -} - -/// @brief Verifies that loss of connectivity to Postgres is handled correctly. -TEST_F(PgSqlConfigBackendDHCPv6DbLostCallbackTest, testDbLostAndFailedCallbackMultiThreading) { - MultiThreadingTest mt(true); - testDbLostAndFailedCallback(); -} - -/// @brief Verifies that loss of connectivity to Postgres is handled correctly. -TEST_F(PgSqlConfigBackendDHCPv6DbLostCallbackTest, testDbLostAndRecoveredAfterTimeoutCallback) { - MultiThreadingTest mt(false); - testDbLostAndRecoveredAfterTimeoutCallback(); -} - -/// @brief Verifies that loss of connectivity to Postgres is handled correctly. -TEST_F(PgSqlConfigBackendDHCPv6DbLostCallbackTest, - testDbLostAndRecoveredAfterTimeoutCallbackMultiThreading) { - MultiThreadingTest mt(true); - testDbLostAndRecoveredAfterTimeoutCallback(); -} - -/// @brief Verifies that loss of connectivity to Postgres is handled correctly. -TEST_F(PgSqlConfigBackendDHCPv6DbLostCallbackTest, testDbLostAndFailedAfterTimeoutCallback) { - MultiThreadingTest mt(false); - testDbLostAndFailedAfterTimeoutCallback(); -} - -/// @brief Verifies that loss of connectivity to Postgres is handled correctly. -TEST_F(PgSqlConfigBackendDHCPv6DbLostCallbackTest, - testDbLostAndFailedAfterTimeoutCallbackMultiThreading) { - MultiThreadingTest mt(true); - testDbLostAndFailedAfterTimeoutCallback(); -} - -} // namespace