]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#716,!412] Documented and tested server selection for shared networks.
authorMarcin Siodelski <marcin@isc.org>
Tue, 9 Jul 2019 14:40:33 +0000 (16:40 +0200)
committerMarcin Siodelski <marcin@isc.org>
Tue, 9 Jul 2019 18:37:29 +0000 (14:37 -0400)
Also fixed the code where it accepted unsupported selectors. Implemented
deleting the unassigned subnets.

src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc
src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.h
src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc
src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.h
src/hooks/dhcp/mysql_cb/mysql_cb_impl.cc
src/hooks/dhcp/mysql_cb/mysql_cb_impl.h
src/hooks/dhcp/mysql_cb/mysql_query_macros_dhcp.h
src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp4_unittest.cc
src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp6_unittest.cc
src/lib/dhcpsrv/config_backend_dhcp4.h
src/lib/dhcpsrv/config_backend_dhcp6.h

index 21320a45f30c66dd13dd5201a24444dcd7048a78..18fa0c924c13cc17db0479dd2cb34a4cb77ecf78 100644 (file)
@@ -117,6 +117,7 @@ public:
         DELETE_SHARED_NETWORK4_NAME_WITH_TAG,
         DELETE_SHARED_NETWORK4_NAME_ANY,
         DELETE_ALL_SHARED_NETWORKS4,
+        DELETE_ALL_SHARED_NETWORKS4_UNASSIGNED,
         DELETE_SHARED_NETWORK4_SERVER,
         DELETE_OPTION_DEF4_CODE_NAME,
         DELETE_ALL_OPTION_DEFS4,
@@ -1271,6 +1272,11 @@ public:
     /// structure where shared networks should be inserted.
     void getAllSharedNetworks4(const ServerSelector& server_selector,
                                SharedNetwork4Collection& shared_networks) {
+        if (server_selector.amAny()) {
+            isc_throw(InvalidOperation, "fetching all shared networks for ANY "
+                      "server is not supported");
+        }
+
         auto index = (server_selector.amUnassigned() ? GET_ALL_SHARED_NETWORKS4_UNASSIGNED :
                       GET_ALL_SHARED_NETWORKS4);
         MySqlBindingCollection in_bindings;
@@ -1286,6 +1292,11 @@ public:
     void getModifiedSharedNetworks4(const ServerSelector& server_selector,
                                     const boost::posix_time::ptime& modification_ts,
                                     SharedNetwork4Collection& shared_networks) {
+        if (server_selector.amAny()) {
+            isc_throw(InvalidOperation, "fetching modified shared networks for ANY "
+                      "server is not supported");
+        }
+
         MySqlBindingCollection in_bindings = {
             MySqlBinding::createTimestamp(modification_ts)
         };
@@ -1302,9 +1313,13 @@ public:
     void createUpdateSharedNetwork4(const ServerSelector& server_selector,
                                     const SharedNetwork4Ptr& shared_network) {
 
-        if (server_selector.amUnassigned()) {
-            isc_throw(NotImplemented, "managing configuration for no particular server"
-                      " (unassigned) is unsupported at the moment");
+        if (server_selector.amAny()) {
+            isc_throw(InvalidOperation, "creating or updating a shared network for ANY"
+                      " server is not supported");
+
+        } else if (server_selector.amUnassigned()) {
+            isc_throw(NotImplemented, "creating or updating a shared network without"
+                      " assigning it to a server or all servers is not supported");
         }
 
         // Create binding for host reservation mode.
@@ -2390,6 +2405,11 @@ TaggedStatementArray tagged_statements = { {
       MYSQL_DELETE_SHARED_NETWORK_WITH_TAG(dhcp4)
     },
 
+    // Delete all unassigned shared networks.
+    { MySqlConfigBackendDHCPv4Impl::DELETE_ALL_SHARED_NETWORKS4_UNASSIGNED,
+      MYSQL_DELETE_SHARED_NETWORK_UNASSIGNED(dhcp4)
+    },
+
     // Delete associations of a shared network with server.
     { MySqlConfigBackendDHCPv4Impl::DELETE_SHARED_NETWORK4_SERVER,
       MYSQL_DELETE_SHARED_NETWORK_SERVER(dhcp4)
@@ -2828,6 +2848,15 @@ MySqlConfigBackendDHCPv4::deleteSharedNetworkSubnets4(const db::ServerSelector&
 uint64_t
 MySqlConfigBackendDHCPv4::deleteSharedNetwork4(const ServerSelector& server_selector,
                                                const std::string& name) {
+    /// @todo Using UNASSIGNED selector is allowed by the CB API but we don't have
+    /// dedicated query for this at the moment. The user should use ANY to delete
+    /// the shared network by name.
+    if (server_selector.amUnassigned()) {
+        isc_throw(NotImplemented, "deleting an unassigned shared network requires "
+                  "an explicit server tag or using ANY server. The UNASSIGNED server "
+                  "selector is currently not supported");
+    }
+
     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_SHARED_NETWORK4)
         .arg(name);
 
@@ -2844,9 +2873,17 @@ MySqlConfigBackendDHCPv4::deleteSharedNetwork4(const ServerSelector& server_sele
 
 uint64_t
 MySqlConfigBackendDHCPv4::deleteAllSharedNetworks4(const ServerSelector& server_selector) {
+    if (server_selector.amAny()) {
+        isc_throw(InvalidOperation, "deleting all shared networks for ANY server is not"
+                  " supported");
+    }
+
     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_ALL_SHARED_NETWORKS4);
-    uint64_t result = impl_->deleteTransactional(MySqlConfigBackendDHCPv4Impl::DELETE_ALL_SHARED_NETWORKS4,
-                                                 server_selector, "deleting all shared networks",
+
+    int index = (server_selector.amUnassigned() ?
+                 MySqlConfigBackendDHCPv4Impl::DELETE_ALL_SHARED_NETWORKS4_UNASSIGNED :
+                 MySqlConfigBackendDHCPv4Impl::DELETE_ALL_SHARED_NETWORKS4);
+    uint64_t result = impl_->deleteTransactional(index, server_selector, "deleting all shared networks",
                                                  "deleted all shared networks", true);
     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_ALL_SHARED_NETWORKS4_RESULT)
         .arg(result);
index e0f9e05baf24c431368cd1e64f3abfc9d52cbbd9..6cc79b3dc13107a09513f773dac59ce7788261b2 100644 (file)
@@ -22,6 +22,11 @@ class MySqlConfigBackendDHCPv4Impl;
 ///
 /// 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 ConfigBackendDHCPv4, but support for
+/// some of the selectors is not implemented. Whenever this is the case,
+/// the methods throw @c isc::NotImplemented exception.
 class MySqlConfigBackendDHCPv4 : public ConfigBackendDHCPv4 {
 public:
 
index 9dfb2f47e518ba1aaf5f30c17ab1ec81914f2048..c686572ed52379a7990c5060a908a166f2deb38c 100644 (file)
@@ -123,6 +123,7 @@ public:
         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,
@@ -1474,6 +1475,11 @@ public:
     /// structure where shared networks should be inserted.
     void getAllSharedNetworks6(const ServerSelector& server_selector,
                                SharedNetwork6Collection& shared_networks) {
+        if (server_selector.amAny()) {
+            isc_throw(InvalidOperation, "fetching all shared networks for ANY "
+                      "server is not supported");
+        }
+
         auto index = (server_selector.amUnassigned() ? GET_ALL_SHARED_NETWORKS6_UNASSIGNED :
                       GET_ALL_SHARED_NETWORKS6);
         MySqlBindingCollection in_bindings;
@@ -1489,6 +1495,11 @@ public:
     void getModifiedSharedNetworks6(const ServerSelector& server_selector,
                                     const boost::posix_time::ptime& modification_ts,
                                     SharedNetwork6Collection& shared_networks) {
+        if (server_selector.amAny()) {
+            isc_throw(InvalidOperation, "fetching modified shared networks for ANY "
+                      "server is not supported");
+        }
+
         MySqlBindingCollection in_bindings = {
             MySqlBinding::createTimestamp(modification_ts)
         };
@@ -1505,7 +1516,11 @@ public:
     void createUpdateSharedNetwork6(const ServerSelector& server_selector,
                                     const SharedNetwork6Ptr& shared_network) {
 
-        if (server_selector.amUnassigned()) {
+        if (server_selector.amAny()) {
+            isc_throw(InvalidOperation, "creating or updating a shared network for ANY"
+                      " server is not supported");
+
+        } else if (server_selector.amUnassigned()) {
             isc_throw(NotImplemented, "managing configuration for no particular server"
                       " (unassigned) is unsupported at the moment");
         }
@@ -2752,6 +2767,11 @@ TaggedStatementArray tagged_statements = { {
       MYSQL_DELETE_SHARED_NETWORK_WITH_TAG(dhcp6)
     },
 
+    // Delete all unassigned shared networks.
+    { MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SHARED_NETWORKS6_UNASSIGNED,
+      MYSQL_DELETE_SHARED_NETWORK_UNASSIGNED(dhcp6)
+    },
+
     // Delete associations of a shared network with server.
     { MySqlConfigBackendDHCPv6Impl::DELETE_SHARED_NETWORK6_SERVER,
       MYSQL_DELETE_SHARED_NETWORK_SERVER(dhcp6)
@@ -3221,8 +3241,17 @@ MySqlConfigBackendDHCPv6::deleteSharedNetwork6(const ServerSelector& server_sele
 
 uint64_t
 MySqlConfigBackendDHCPv6::deleteAllSharedNetworks6(const ServerSelector& server_selector) {
+    if (server_selector.amAny()) {
+        isc_throw(InvalidOperation, "deleting all shared networks for ANY server is not"
+                  " supported");
+    }
+
     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_ALL_SHARED_NETWORKS6);
-    uint64_t result = impl_->deleteTransactional(MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SHARED_NETWORKS6,
+
+    int index = (server_selector.amUnassigned() ?
+                 MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SHARED_NETWORKS6_UNASSIGNED :
+                 MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SHARED_NETWORKS6);
+    uint64_t result = impl_->deleteTransactional(index,
                                                  server_selector, "deleting all shared networks",
                                                  "deleted all shared networks", true);
     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_ALL_SHARED_NETWORKS6_RESULT)
index ac126d735d70adab6c6936009701496edf67fa6e..d0f612ae57114cb3518d1531f9fd865a63256b88 100644 (file)
@@ -22,6 +22,11 @@ class MySqlConfigBackendDHCPv6Impl;
 ///
 /// 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 MySqlConfigBackendDHCPv6 : public ConfigBackendDHCPv6 {
 public:
 
index ea7f66e1f98960ececbc1958a398d24ae9a4d3f0..1453223220b57b17c54b3e4aecfc6b38ec45169f 100644 (file)
@@ -236,6 +236,12 @@ uint64_t
 MySqlConfigBackendImpl::deleteFromTable(const int index,
                                         const ServerSelector& server_selector,
                                         const std::string& operation) {
+    // When deleting multiple objects we must not use ANY server.
+    if (server_selector.amAny()) {
+        isc_throw(InvalidOperation, "deleting multiple objects for ANY server is not"
+                  " supported");
+    }
+
     MySqlBindingCollection in_bindings;
     return (deleteFromTable(index, server_selector, operation, in_bindings));
 }
index 7e54c1c0635bfdd9a6661a8a3308f4386fd2082d..31edee4ee2e921d9e17b3f5d3613857fd43dea4d 100644 (file)
@@ -261,13 +261,8 @@ public:
                              const std::string& operation,
                              db::MySqlBindingCollection& in_bindings) {
 
-        if (server_selector.amUnassigned()) {
-            isc_throw(NotImplemented, "managing configuration for no particular server"
-                      " (unassigned) is unsupported at the moment");
-        }
-
         // For ANY server, we use queries that lack server tag.
-        if (!server_selector.amAny()) {
+        if (!server_selector.amAny() && !server_selector.amUnassigned()) {
             auto tag = getServerTag(server_selector, operation);
             in_bindings.insert(in_bindings.begin(), db::MySqlBinding::createString(tag));
         }
@@ -307,6 +302,13 @@ public:
                              const db::ServerSelector& server_selector,
                              const std::string& operation,
                              KeyType key) {
+        // When deleting by some key, we must use ANY.
+        if (server_selector.amUnassigned()) {
+            isc_throw(NotImplemented, "deleting an unassigned object requires "
+                      "an explicit server tag or using ANY server. The UNASSIGNED "
+                      "server selector is currently not supported");
+        }
+
         db::MySqlBindingCollection in_bindings;
 
         if (db::MySqlBindingTraits<KeyType>::column_type == MYSQL_TYPE_STRING) {
index 8e1b0eeecb260af0c0717e9cd35ac10d8d411188..d37860eedcbda0ea13b8b71b9d9174f6a6408bfc 100644 (file)
@@ -704,6 +704,12 @@ namespace {
     "DELETE n FROM " #table_prefix "_shared_network AS n " \
     #__VA_ARGS__
 
+#define MYSQL_DELETE_SHARED_NETWORK_UNASSIGNED(table_prefix, ...) \
+    "DELETE n FROM " #table_prefix "_shared_network AS n " \
+    "LEFT JOIN " #table_prefix "_shared_network_server AS a" \
+    "  ON n.id = a.shared_network_id " \
+    "WHERE a.shared_network_id IS NULL " #__VA_ARGS__
+
 #endif
 
 #ifndef MYSQL_DELETE_SHARED_NETWORK_SERVER
index 020d8f59c9244a92dc2dc717e007edc37106d1d5..f1ab1bf3239725e3a580f1b4f6c1ea23dc732f9e 100644 (file)
@@ -1528,6 +1528,21 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getSharedNetwork4) {
     }
 }
 
+// Test that getSharedNetwork4 throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv4Test, getSharedNetwork4Selectors) {
+    // Supported selectors.
+    EXPECT_NO_THROW(cbptr_->getSharedNetwork4(ServerSelector::ANY(), "level1"));
+    EXPECT_NO_THROW(cbptr_->getSharedNetwork4(ServerSelector::UNASSIGNED(), "level1"));
+    EXPECT_NO_THROW(cbptr_->getSharedNetwork4(ServerSelector::ALL(), "level1"));
+    EXPECT_NO_THROW(cbptr_->getSharedNetwork4(ServerSelector::ONE("server1"), "level1"));
+
+    // Not supported selectors.
+    EXPECT_THROW(cbptr_->getSharedNetwork4(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(MySqlConfigBackendDHCPv4Test, createUpdateSharedNetwork4) {
@@ -1583,6 +1598,33 @@ TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateSharedNetwork4) {
     EXPECT_FALSE(network->hasServerTag(ServerTag()));
 }
 
+// Test that craeteUpdateSharedNetwork4 throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateSharedNetwork4Selectors) {
+    ASSERT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[0]));
+    ASSERT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[2]));
+
+    // Supported selectors.
+    SharedNetwork4Ptr shared_network(new SharedNetwork4("all"));
+    EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(),
+                                                       shared_network));
+    shared_network.reset(new SharedNetwork4("one"));
+    EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::ONE("server1"),
+                                                       shared_network));
+    shared_network.reset(new SharedNetwork4("multiple"));
+    EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::MULTIPLE({ "server1", "server2" }),
+                                                       shared_network));
+
+    // Not supported server selectors.
+    EXPECT_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::ANY(), shared_network),
+                 isc::InvalidOperation);
+
+    // Not implemented server selectors.
+    EXPECT_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::UNASSIGNED(),
+                                                    shared_network),
+                 isc::NotImplemented);
+}
+
 // Test that the information about unspecified optional parameters gets
 // propagated to the database.
 TEST_F(MySqlConfigBackendDHCPv4Test, getSharedNetwork4WithOptionalUnspecified) {
@@ -1763,6 +1805,20 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getAllSharedNetworks4) {
     EXPECT_TRUE(subnet->getSharedNetworkName().empty());
 }
 
+// Test that getAllSharedNetworks4 throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv4Test, getAllSharedNetworks4Selectors) {
+    // Supported selectors.
+    EXPECT_NO_THROW(cbptr_->getAllSharedNetworks4(ServerSelector::UNASSIGNED()));
+    EXPECT_NO_THROW(cbptr_->getAllSharedNetworks4(ServerSelector::ALL()));
+    EXPECT_NO_THROW(cbptr_->getAllSharedNetworks4(ServerSelector::ONE("server1")));
+    EXPECT_NO_THROW(cbptr_->getAllSharedNetworks4(ServerSelector::MULTIPLE({ "server1", "server2" })));
+
+    // Not supported selectors.
+    EXPECT_THROW(cbptr_->getAllSharedNetworks4(ServerSelector::ANY()),
+                 isc::InvalidOperation);
+}
+
 // Test that shared networks with different server associations are returned.
 TEST_F(MySqlConfigBackendDHCPv4Test, getAllSharedNetworks4WithServerTags) {
     auto shared_network1 = test_networks_[0];
@@ -1872,6 +1928,25 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getModifiedSharedNetworks4) {
     ASSERT_TRUE(networks.empty());
 }
 
+// Test that getModifiedSharedNetworks4 throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv4Test, getModifiedSharedNetworks4Selectors) {
+    // Supported selectors.
+    EXPECT_NO_THROW(cbptr_->getModifiedSharedNetworks4(ServerSelector::UNASSIGNED(),
+                                                       timestamps_["yesterday"]));
+    EXPECT_NO_THROW(cbptr_->getModifiedSharedNetworks4(ServerSelector::ALL(),
+                                                       timestamps_["yesterday"]));
+    EXPECT_NO_THROW(cbptr_->getModifiedSharedNetworks4(ServerSelector::ONE("server1"),
+                                                       timestamps_["yesterday"]));
+    EXPECT_NO_THROW(cbptr_->getModifiedSharedNetworks4(ServerSelector::MULTIPLE({ "server1", "server2" }),
+                                                       timestamps_["yesterday"]));
+
+    // Not supported selectors.
+    EXPECT_THROW(cbptr_->getModifiedSharedNetworks4(ServerSelector::ANY(),
+                                                    timestamps_["yesterday"]),
+                 isc::InvalidOperation);
+}
+
 // Test that selected shared network can be deleted.
 TEST_F(MySqlConfigBackendDHCPv4Test, deleteSharedNetwork4) {
     // Create two servers in the database.
@@ -1961,19 +2036,56 @@ TEST_F(MySqlConfigBackendDHCPv4Test, deleteSharedNetwork4) {
     test_delete("one server", ServerSelector::ONE("server1"), shared_network3);
 }
 
+// Test that deleteSharedNetwork4 throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv4Test, deleteSharedNetwork4Selectors) {
+    // Supported selectors.
+    EXPECT_NO_THROW(cbptr_->deleteSharedNetwork4(ServerSelector::ANY(), "level1"));
+    EXPECT_NO_THROW(cbptr_->deleteSharedNetwork4(ServerSelector::ALL(), "level1"));
+    EXPECT_NO_THROW(cbptr_->deleteSharedNetwork4(ServerSelector::ONE("server1"), "level1"));
+
+    // Not supported selectors.
+    EXPECT_THROW(cbptr_->deleteSharedNetwork4(ServerSelector::MULTIPLE({ "server1", "server2" }),
+                                           "level1"),
+                 isc::InvalidOperation);
+
+    // Not implemented selectors.
+    EXPECT_THROW(cbptr_->deleteSharedNetwork4(ServerSelector::UNASSIGNED(), "level1"),
+                 isc::NotImplemented);
+}
+
+// Test that deleteAllSharedNetworks4 throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv4Test, deleteAllSharedNetworks4Selectors) {
+    // Supported selectors.
+    EXPECT_NO_THROW(cbptr_->deleteAllSharedNetworks4(ServerSelector::UNASSIGNED()));
+    EXPECT_NO_THROW(cbptr_->deleteAllSharedNetworks4(ServerSelector::ALL()));
+    EXPECT_NO_THROW(cbptr_->deleteAllSharedNetworks4(ServerSelector::ONE("server1")));
+
+    // Not supported selectors.
+    EXPECT_THROW(cbptr_->deleteAllSharedNetworks4(ServerSelector::ANY()),
+                 isc::InvalidOperation);
+    EXPECT_THROW(cbptr_->deleteAllSharedNetworks4(ServerSelector::MULTIPLE({ "server1", "server2" })),
+                 isc::InvalidOperation);
+}
+
 // Test that it is possible to retrieve and delete orphaned shared network.
 TEST_F(MySqlConfigBackendDHCPv4Test, unassignedSharedNetwork) {
     // Create the server.
     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[0]));
 
-    // Create the shared network and associate it with the server1.
+    // 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_->createUpdateSharedNetwork4(ServerSelector::ONE("server1"), shared_network)
     );
+    EXPECT_NO_THROW(
+        cbptr_->createUpdateSharedNetwork4(ServerSelector::ONE("server1"), shared_network2)
+    );
 
-    // Delete the server. The shared network should be preserved but is
-    // considered orhpaned, i.e. does not belong to any server.
+    // Delete the server. The shared networks should be preserved but are
+    // considered orhpaned, i.e. do not belong to any server.
     uint64_t deleted_count = 0;
     EXPECT_NO_THROW(deleted_count = cbptr_->deleteServer4(ServerTag("server1")));
     EXPECT_EQ(1, deleted_count);
@@ -2004,16 +2116,16 @@ TEST_F(MySqlConfigBackendDHCPv4Test, unassignedSharedNetwork) {
 
     // Also if we ask for all unassigned networks it should be returned.
     EXPECT_NO_THROW(returned_networks = cbptr_->getAllSharedNetworks4(ServerSelector::UNASSIGNED()));
-    ASSERT_EQ(1, returned_networks.size());
+    ASSERT_EQ(2, returned_networks.size());
 
     // And all modified.
     EXPECT_NO_THROW(
         returned_networks = cbptr_->getModifiedSharedNetworks4(ServerSelector::UNASSIGNED(),
                                                                timestamps_["two days ago"])
     );
-    ASSERT_EQ(1, returned_networks.size());
+    ASSERT_EQ(2, returned_networks.size());
 
-    // If we ask for any network with this name, it should be returned too.
+    // If we ask for any network by name, it should be returned too.
     EXPECT_NO_THROW(returned_network = cbptr_->getSharedNetwork4(ServerSelector::ANY(),
                                                                  "level1"));
     ASSERT_TRUE(returned_network);
@@ -2037,6 +2149,12 @@ TEST_F(MySqlConfigBackendDHCPv4Test, unassignedSharedNetwork) {
         deleted_count = cbptr_->deleteSharedNetwork4(ServerSelector::ANY(), "level1")
     );
     EXPECT_EQ(1, deleted_count);
+
+    // We can delete all second networks using UNASSIGNED selector.
+    EXPECT_NO_THROW(
+        deleted_count = cbptr_->deleteAllSharedNetworks4(ServerSelector::UNASSIGNED());
+    );
+    EXPECT_EQ(1, deleted_count);
 }
 
 // Test that lifetimes in shared networks are handled as expected.
index 19fbe316b30495246a107d48879ef39ed7fc71ab..c7b31656ef8b2251e1fb99b2c8d5bd1396e995b4 100644 (file)
@@ -1543,6 +1543,21 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getSharedNetwork6) {
     }
 }
 
+// Test that getSharedNetwork6 throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv6Test, 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(MySqlConfigBackendDHCPv6Test, createUpdateSharedNetwork6) {
@@ -1598,6 +1613,33 @@ TEST_F(MySqlConfigBackendDHCPv6Test, createUpdateSharedNetwork6) {
     EXPECT_FALSE(network->hasServerTag(ServerTag()));
 }
 
+// Test that craeteUpdateSharedNetwork6 throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv6Test, 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(MySqlConfigBackendDHCPv6Test, getSharedNetwork6WithOptionalUnspecified) {
@@ -1779,6 +1821,20 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getAllSharedNetworks6) {
     EXPECT_TRUE(subnet->getSharedNetworkName().empty());
 }
 
+// Test that getAllSharedNetworks6 throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv6Test, 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(MySqlConfigBackendDHCPv6Test, getAllSharedNetworks6WithServerTags) {
     auto shared_network1 = test_networks_[0];
@@ -1888,6 +1944,25 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getModifiedSharedNetworks6) {
     ASSERT_TRUE(networks.empty());
 }
 
+// Test that getModifiedSharedNetworks6 throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv6Test, 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(MySqlConfigBackendDHCPv6Test, deleteSharedNetwork6) {
     // Create two servers in the database.
@@ -1977,19 +2052,56 @@ TEST_F(MySqlConfigBackendDHCPv6Test, deleteSharedNetwork6) {
     test_delete("one server", ServerSelector::ONE("server1"), shared_network3);
 }
 
+// Test that deleteSharedNetwork6 throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv6Test, 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(MySqlConfigBackendDHCPv6Test, 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(MySqlConfigBackendDHCPv6Test, unassignedSharedNetwork) {
     // Create the server.
     EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[0]));
 
-    // Create the shared network and associate it with the server1.
+    // 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 network should be preserved but is
-    // considered orhpaned, i.e. does not belong to any server.
+    // Delete the server. The shared networks should be preserved but are
+    // considered orhpaned, 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);
@@ -2020,16 +2132,16 @@ TEST_F(MySqlConfigBackendDHCPv6Test, unassignedSharedNetwork) {
 
     // Also if we ask for all unassigned networks it should be returned.
     EXPECT_NO_THROW(returned_networks = cbptr_->getAllSharedNetworks6(ServerSelector::UNASSIGNED()));
-    ASSERT_EQ(1, returned_networks.size());
+    ASSERT_EQ(2, returned_networks.size());
 
     // And all modified.
     EXPECT_NO_THROW(
         returned_networks = cbptr_->getModifiedSharedNetworks6(ServerSelector::UNASSIGNED(),
                                                                timestamps_["two days ago"])
     );
-    ASSERT_EQ(1, returned_networks.size());
+    ASSERT_EQ(2, returned_networks.size());
 
-    // If we ask for any network with this name, it should be returned too.
+    // 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);
@@ -2053,6 +2165,12 @@ TEST_F(MySqlConfigBackendDHCPv6Test, unassignedSharedNetwork) {
         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.
index c155398868316d3434c253fcf5c4f57323ca559f..45527a584f3c971cc6f80e3c093672fcc94508be 100644 (file)
@@ -29,6 +29,59 @@ namespace dhcp {
 ///
 /// All POSIX times specified in the methods belonging to this
 /// class must be local times.
+///
+/// Below, we describe the general rules of using the server selectors
+/// when creating, updating, fetching and deleting the configuration
+/// elements from the backends. The detailed information can be found
+/// in the descriptions of the individual methods. The backend
+/// implementations must not be in conflict with the rules described
+/// here but may sometimes lack some functionality and not support
+/// some of the server selectors for some API calls. In such cases
+/// the backend's documentation should be clear about these cases
+/// and document the exceptions thrown when unsupported selector is
+/// used for a given method.
+///
+/// The @c ServerSelector class defines 5 types of selectors:
+/// - ANY: server tag/id is not a part of the database query, i.e. the
+///   object in the database is identified by some unique property,
+///   e.g. subnet identifier, shared network name etc.
+///
+/// - UNASSIGNED: query pertains to the objects in the database which
+///   are associated with no particular server (including the logical
+///   server "all"). Objects associated with any server are never
+///   selected.
+///
+/// - ALL: query pertains only to the objects in the database which are
+///   associated with the logical server "all". Those objects are shared
+///   between all servers using the database. This server selector never
+///   returns objects explicitly associated with the particular servers
+///   defined by the user.
+///
+/// - ONE: query pertains to the objects used by one particular server.
+///   The server uses both the objects explicitly associated with it and
+///   and the objects associated with the logical server "all". Therefore
+///   the result returned for this server selector combines configuration
+///   elements associated with this server and with "all" servers. In case
+///   if there are two instances of the configuration information, one
+///   associated with "all" servers and one associated with the server,
+///   the information associated with the server takes precedence.
+///   When using this selector to delete objects from the database, the
+///   deletion pertains only to the objects associated with the given
+///   server tag. It doesn't delete the objects associated with "all"
+///   servers.
+///
+/// - MULTIPLE: query pertains to the objects used by multiple servers
+///   listed in the selector. It allows for querying for a list of
+///   objects associated with multiple servers and/or logical server
+///   "all".
+///
+/// There are limitations imposed on the API calls what server selectors
+/// are allowed for them. Configuration Backend implementations must not
+/// be in conflict with those limitations. In particular, the implementation
+/// must not permit for server selectors which are not allowed here.
+/// However, the backend implementation may be more restrictive and not
+/// allow some of the server selectors for some API calls. This should,
+/// however, be properly documented.
 class ConfigBackendDHCPv4 : public cb::BaseConfigBackend {
 public:
 
@@ -80,6 +133,9 @@ public:
 
     /// @brief Retrieves shared network by name.
     ///
+    /// Allowed server selectors: ANY, UNASSIGNED, ALL, ONE.
+    /// Not allowed server selector: MULTIPLE.
+    ///
     /// @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.
@@ -89,6 +145,9 @@ public:
 
     /// @brief Retrieves all shared networks.
     ///
+    /// Allowed server selectors: UNASSIGNED, ALL, ONE, MULTIPLE.
+    /// Not allowed server selector: ANY.
+    ///
     /// @param server_selector Server selector.
     /// @return Collection of shared network or empty collection if
     /// no shared network found.
@@ -97,6 +156,9 @@ public:
 
     /// @brief Retrieves shared networks modified after specified time.
     ///
+    /// Allowed server selectors: UNASSIGNED, ALL, ONE, MULTIPLE.
+    /// Not allowed server selector: ANY.
+    ///
     /// @param server_selector Server selector.
     /// @param modification_time Lower bound shared network modification time.
     /// @return Collection of shared network or empty collection if
@@ -256,6 +318,9 @@ public:
 
     /// @brief Creates or updates a shared network.
     ///
+    /// Allowed server selectors: UNASSIGNED, ALL, ONE, MULTIPLE.
+    /// Not allowed server selector: ANY.
+    ///
     /// @param server_selector Server selector.
     /// @param shared_network Shared network to be added or updated.
     virtual void
@@ -363,15 +428,21 @@ public:
 
     /// @brief Deletes shared network by name.
     ///
+    /// Allowed server selectors: ANY, UNASSIGNED, ALL, ONE.
+    /// Not allowed server selectors: MULTIPLE.
+    ///
     /// @param server_selector Server selector.
     /// @param name Name of the shared network to be deleted.
-    /// @return Number of deleted shared networks..
+    /// @return Number of deleted shared networks.
     virtual uint64_t
     deleteSharedNetwork4(const db::ServerSelector& server_selector,
                          const std::string& name) = 0;
 
     /// @brief Deletes all shared networks.
     ///
+    /// Allowed server selectors: UNASSIGNED, ALL, ONE.
+    /// Not allowed server selectors: ANY, MULTIPLE.
+    ///
     /// @param server_selector Server selector.
     /// @return Number of deleted shared networks.
     virtual uint64_t
index 3a0e3c411a2ba3607a2d22e3689ffebdbf6c8415..fd25b6a867014287e87fb8c40dff06a69fe47756 100644 (file)
@@ -30,6 +30,59 @@ namespace dhcp {
 ///
 /// All POSIX times specified in the methods belonging to this
 /// class must be local times.
+///
+/// Below, we describe the general rules of using the server selectors
+/// when creating, updating, fetching and deleting the configuration
+/// elements from the backends. The detailed information can be found
+/// in the descriptions of the individual methods. The backend
+/// implementations must not be in conflict with the rules described
+/// here but may sometimes lack some functionality and not support
+/// some of the server selectors for some API calls. In such cases
+/// the backend's documentation should be clear about these cases
+/// and document the exceptions thrown when unsupported selector is
+/// used for a given method.
+///
+/// The @c ServerSelector class defines 5 types of selectors:
+/// - ANY: server tag/id is not a part of the database query, i.e. the
+///   object in the database is identified by some unique property,
+///   e.g. subnet identifier, shared network name etc.
+///
+/// - UNASSIGNED: query pertains to the objects in the database which
+///   are associated with no particular server (including the logical
+///   server "all"). Objects associated with any server are never
+///   selected.
+///
+/// - ALL: query pertains only to the objects in the database which are
+///   associated with the logical server "all". Those objects are shared
+///   between all servers using the database. This server selector never
+///   returns objects explicitly associated with the particular servers
+///   defined by the user.
+///
+/// - ONE: query pertains to the objects used by one particular server.
+///   The server uses both the objects explicitly associated with it and
+///   and the objects associated with the logical server "all". Therefore
+///   the result returned for this server selector combines configuration
+///   elements associated with this server and with "all" servers. In case
+///   if there are two instances of the configuration information, one
+///   associated with "all" servers and one associated with the server,
+///   the information associated with the server takes precedence.
+///   When using this selector to delete objects from the database, the
+///   deletion pertains only to the objects associated with the given
+///   server tag. It doesn't delete the objects associated with "all"
+///   servers.
+///
+/// - MULTIPLE: query pertains to the objects used by multiple servers
+///   listed in the selector. It allows for querying for a list of
+///   objects associated with multiple servers and/or logical server
+///   "all".
+///
+/// There are limitations imposed on the API calls what server selectors
+/// are allowed for them. Configuration Backend implementations must not
+/// be in conflict with those limitations. In particular, the implementation
+/// must not permit for server selectors which are not allowed here.
+/// However, the backend implementation may be more restrictive and not
+/// allow some of the server selectors for some API calls. This should,
+/// however, be properly documented.
 class ConfigBackendDHCPv6 : public cb::BaseConfigBackend {
 public:
 
@@ -72,6 +125,9 @@ public:
 
     /// @brief Retrieves subnets modified after specified time.
     ///
+    /// Allowed server selectors: UNASSIGNED, ALL, ONE, MULTIPLE.
+    /// Not allowed server selector: ANY.
+    ///
     /// @param server_selector Server selector.
     /// @param modification_time Lower bound subnet modification time.
     /// @return Collection of subnets or empty collection if no subnet found.
@@ -81,6 +137,9 @@ public:
 
     /// @brief Retrieves shared network by name.
     ///
+    /// Allowed server selectors: ANY, UNASSIGNED, ALL, ONE.
+    /// Not allowed server selector: MULTIPLE.
+    ///
     /// @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.
@@ -90,6 +149,9 @@ public:
 
     /// @brief Retrieves all shared networks.
     ///
+    /// Allowed server selectors: UNASSIGNED, ALL, ONE, MULTIPLE.
+    /// Not allowed server selector: ANY.
+    ///
     /// @param server_selector Server selector.
     /// @return Collection of shared network or empty collection if
     /// no shared network found.
@@ -257,6 +319,9 @@ public:
 
     /// @brief Creates or updates a shared network.
     ///
+    /// Allowed server selectors: UNASSIGNED, ALL, ONE, MULTIPLE.
+    /// Not allowed server selector: ANY.
+    ///
     /// @param server_selector Server selector.
     /// @param shared_network Shared network to be added or updated.
     virtual void
@@ -378,6 +443,9 @@ public:
 
     /// @brief Deletes shared network by name.
     ///
+    /// Allowed server selectors: ANY, UNASSIGNED, ALL, ONE.
+    /// Not allowed server selectors: MULTIPLE.
+    ///
     /// @param server_selector Server selector.
     /// @param name Name of the shared network to be deleted.
     /// @return Number of deleted shared networks..
@@ -387,6 +455,9 @@ public:
 
     /// @brief Deletes all shared networks.
     ///
+    /// Allowed server selectors: UNASSIGNED, ALL, ONE.
+    /// Not allowed server selectors: ANY, MULTIPLE.
+    ///
     /// @param server_selector Server selector.
     /// @return Number of deleted shared networks.
     virtual uint64_t