]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#642,!373] Updated MySQL Config Backend with simple server mgmt functions.
authorMarcin Siodelski <marcin@isc.org>
Wed, 12 Jun 2019 18:37:16 +0000 (20:37 +0200)
committerMarcin Siodelski <marcin@isc.org>
Thu, 27 Jun 2019 18:51:31 +0000 (14:51 -0400)
25 files changed:
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_cb_messages.cc
src/hooks/dhcp/mysql_cb/mysql_cb_messages.h
src/hooks/dhcp/mysql_cb/mysql_cb_messages.mes
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/config_backend/constants.h
src/lib/dhcpsrv/config_backend_dhcp4.h
src/lib/dhcpsrv/config_backend_dhcp6.h
src/lib/dhcpsrv/config_backend_pool_dhcp4.cc
src/lib/dhcpsrv/config_backend_pool_dhcp4.h
src/lib/dhcpsrv/config_backend_pool_dhcp6.cc
src/lib/dhcpsrv/config_backend_pool_dhcp6.h
src/lib/dhcpsrv/testutils/test_config_backend_dhcp4.cc
src/lib/dhcpsrv/testutils/test_config_backend_dhcp4.h
src/lib/dhcpsrv/testutils/test_config_backend_dhcp6.cc
src/lib/dhcpsrv/testutils/test_config_backend_dhcp6.h
src/share/database/scripts/mysql/dhcpdb_create.mysql
src/share/database/scripts/mysql/upgrade_8.0_to_9.0.sh.in [new file with mode: 0644]

index bdb76ccfe1c763acaba30814539f1549322a3e28..58a31c34da45e8e471b52cd9eebf9c3228df7bc5 100644 (file)
@@ -79,6 +79,8 @@ public:
         GET_OPTION4_POOL_ID_CODE_SPACE,
         GET_OPTION4_SHARED_NETWORK_CODE_SPACE,
         GET_AUDIT_ENTRIES4_TIME,
+        GET_SERVER4,
+        GET_ALL_SERVERS4,
         INSERT_GLOBAL_PARAMETER4,
         INSERT_GLOBAL_PARAMETER4_SERVER,
         INSERT_SUBNET4,
@@ -90,6 +92,7 @@ public:
         INSERT_OPTION_DEF4_SERVER,
         INSERT_OPTION4,
         INSERT_OPTION4_SERVER,
+        INSERT_SERVER4,
         UPDATE_GLOBAL_PARAMETER4,
         UPDATE_SUBNET4,
         UPDATE_SHARED_NETWORK4,
@@ -98,6 +101,7 @@ public:
         UPDATE_OPTION4_SUBNET_ID,
         UPDATE_OPTION4_POOL_ID,
         UPDATE_OPTION4_SHARED_NETWORK,
+        UPDATE_SERVER4,
         DELETE_GLOBAL_PARAMETER4,
         DELETE_ALL_GLOBAL_PARAMETERS4,
         DELETE_SUBNET4_ID,
@@ -115,6 +119,8 @@ public:
         DELETE_OPTION4_SHARED_NETWORK,
         DELETE_OPTIONS4_SUBNET_ID,
         DELETE_OPTIONS4_SHARED_NETWORK,
+        DELETE_SERVER4,
+        DELETE_ALL_SERVERS4,
         NUM_STATEMENTS
     };
 
@@ -1886,6 +1892,7 @@ public:
                                     true,
                                     in_bindings));
     }
+
 };
 
 namespace {
@@ -2032,6 +2039,16 @@ TaggedStatementArray tagged_statements = { {
       MYSQL_GET_AUDIT_ENTRIES_TIME(dhcp4)
     },
 
+    // Retrieves a server by tag.
+    { MySqlConfigBackendDHCPv4Impl::GET_SERVER4,
+      MYSQL_GET_SERVER(dhcp4)
+    },
+
+    // Retrieves all servers.
+    { MySqlConfigBackendDHCPv4Impl::GET_ALL_SERVERS4,
+      MYSQL_GET_ALL_SERVERS(dhcp4)
+    },
+
     // Insert global parameter.
     { MySqlConfigBackendDHCPv4Impl::INSERT_GLOBAL_PARAMETER4,
       MYSQL_INSERT_GLOBAL_PARAMETER(dhcp4)
@@ -2136,6 +2153,11 @@ TaggedStatementArray tagged_statements = { {
       MYSQL_INSERT_OPTION_SERVER(dhcp4)
     },
 
+    // Insert server with server tag and description.
+    { MySqlConfigBackendDHCPv4Impl::INSERT_SERVER4,
+      MYSQL_INSERT_SERVER(dhcp4)
+    },
+
     // Update existing global parameter.
     { MySqlConfigBackendDHCPv4Impl::UPDATE_GLOBAL_PARAMETER4,
       MYSQL_UPDATE_GLOBAL_PARAMETER(dhcp4)
@@ -2223,6 +2245,11 @@ TaggedStatementArray tagged_statements = { {
       MYSQL_UPDATE_OPTION4(AND o.scope_id = 4 AND o.shared_network_name = ? AND o.code = ? AND o.space = ?)
     },
 
+    // Update existing server, e.g. server description.
+    { MySqlConfigBackendDHCPv4Impl::UPDATE_SERVER4,
+      MYSQL_UPDATE_SERVER(dhcp4)
+    },
+
     // Delete global parameter by name.
     { MySqlConfigBackendDHCPv4Impl::DELETE_GLOBAL_PARAMETER4,
       MYSQL_DELETE_GLOBAL_PARAMETER(dhcp4, AND g.name = ?)
@@ -2308,6 +2335,16 @@ TaggedStatementArray tagged_statements = { {
     // Delete options belonging to a shared_network.
     { MySqlConfigBackendDHCPv4Impl::DELETE_OPTIONS4_SHARED_NETWORK,
       MYSQL_DELETE_OPTION(dhcp4, AND o.scope_id = 4 AND o.shared_network_name = ?)
+    },
+
+    // Delete a server by tag.
+    { MySqlConfigBackendDHCPv4Impl::DELETE_SERVER4,
+      MYSQL_DELETE_SERVER(dhcp4)
+    },
+
+    // Deletes all servers except logical server 'all'.
+    { MySqlConfigBackendDHCPv4Impl::DELETE_ALL_SERVERS4,
+      MYSQL_DELETE_ALL_SERVERS(dhcp4)
     }
 }
 };
@@ -2532,14 +2569,22 @@ MySqlConfigBackendDHCPv4::getRecentAuditEntries(const db::ServerSelector& server
 
 ServerCollection
 MySqlConfigBackendDHCPv4::getAllServers4() const {
-    isc_throw(NotImplemented, "MySqlConfigBackendDHCPv4::getAllServers4"
-              " is not implemented");
+    ServerCollection servers;
+
+    LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_ALL_SERVERS4);
+    impl_->getAllServers(MySqlConfigBackendDHCPv4Impl::GET_ALL_SERVERS4,
+                         servers);
+
+    LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_ALL_SERVERS4_RESULT)
+        .arg(servers.size());
+    return (servers);
 }
 
 ServerPtr
-MySqlConfigBackendDHCPv4::getServer4(const data::ServerTag& /* server_tag */) const {
-    isc_throw(NotImplemented, "MySqlConfigBackendDHCPv4::getServer4"
-              " is not implemented");
+MySqlConfigBackendDHCPv4::getServer4(const data::ServerTag& server_tag) const {
+    LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_SERVER4)
+        .arg(server_tag.get());
+    return (impl_->getServer(MySqlConfigBackendDHCPv4Impl::GET_SERVER4, server_tag));
 }
 
 void
@@ -2611,9 +2656,13 @@ MySqlConfigBackendDHCPv4::createUpdateGlobalParameter4(const ServerSelector& ser
 }
 
 void
-MySqlConfigBackendDHCPv4::createUpdateServer4(const ServerPtr& /* server */) {
-    isc_throw(NotImplemented, "MySqlConfigBackendDHCPv4::createUpdateServer4"
-              " is not implemented");
+MySqlConfigBackendDHCPv4::createUpdateServer4(const ServerPtr& server) {
+    LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_CREATE_UPDATE_SERVER4)
+        .arg(server->getServerTag());
+    impl_->createUpdateServer(MySqlConfigBackendDHCPv4Impl::CREATE_AUDIT_REVISION,
+                              MySqlConfigBackendDHCPv4Impl::INSERT_SERVER4,
+                              MySqlConfigBackendDHCPv4Impl::UPDATE_SERVER4,
+                              server);
 }
 
 uint64_t
@@ -2792,15 +2841,18 @@ MySqlConfigBackendDHCPv4::deleteAllGlobalParameters4(const ServerSelector& serve
 }
 
 uint64_t
-MySqlConfigBackendDHCPv4::deleteServer4(const std::string& /* server_tag */) {
-    isc_throw(NotImplemented, "MySqlConfigBackendDHCPv4::deleteServer4"
-              " is not implemented");
+MySqlConfigBackendDHCPv4::deleteServer4(const ServerTag& server_tag) {
+    uint64_t result = impl_->deleteServer(MySqlConfigBackendDHCPv4Impl::CREATE_AUDIT_REVISION,
+                                          MySqlConfigBackendDHCPv4Impl::DELETE_SERVER4,
+                                          server_tag.get());
+    return (result);
 }
 
 uint64_t
 MySqlConfigBackendDHCPv4::deleteAllServers4() {
-    isc_throw(NotImplemented, "MySqlConfigBackendDHCPv4::deleteAllServers4"
-              " is not implemented");
+    uint64_t result = impl_->deleteAllServers(MySqlConfigBackendDHCPv4Impl::CREATE_AUDIT_REVISION,
+                                              MySqlConfigBackendDHCPv4Impl::DELETE_ALL_SERVERS4);
+    return (result);
 }
 
 std::string
index 64f5e52efecb1ceb3133147f05a674781999f19b..961aa9d7e3832c78a5c33220d7ef594151c5c50f 100644 (file)
@@ -450,7 +450,7 @@ public:
     /// @param server_tag Tag of the server to be deleted.
     /// @return Number of deleted servers.
     virtual uint64_t
-    deleteServer4(const std::string& server_tag);
+    deleteServer4(const data::ServerTag& server_tag);
 
     /// @brief Deletes all servers from the backend except the logical
     /// server 'all'.
index 2e99e43dc8467e17ed023163fd0f5656f7e898ab..089e0f42f4ef49a2bedeb75aba295316d665d8c7 100644 (file)
@@ -82,6 +82,8 @@ public:
         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,
@@ -94,6 +96,7 @@ public:
         INSERT_OPTION_DEF6_SERVER,
         INSERT_OPTION6,
         INSERT_OPTION6_SERVER,
+        INSERT_SERVER6,
         UPDATE_GLOBAL_PARAMETER6,
         UPDATE_SUBNET6,
         UPDATE_SHARED_NETWORK6,
@@ -103,6 +106,7 @@ public:
         UPDATE_OPTION6_POOL_ID,
         UPDATE_OPTION6_PD_POOL_ID,
         UPDATE_OPTION6_SHARED_NETWORK,
+        UPDATE_SERVER6,
         DELETE_GLOBAL_PARAMETER6,
         DELETE_ALL_GLOBAL_PARAMETERS6,
         DELETE_SUBNET6_ID,
@@ -122,6 +126,8 @@ public:
         DELETE_OPTION6_SHARED_NETWORK,
         DELETE_OPTIONS6_SUBNET_ID,
         DELETE_OPTIONS6_SHARED_NETWORK,
+        DELETE_SERVER6,
+        DELETE_ALL_SERVERS6,
         NUM_STATEMENTS
     };
 
@@ -2380,6 +2386,16 @@ TaggedStatementArray tagged_statements = { {
       MYSQL_GET_AUDIT_ENTRIES_TIME(dhcp6)
     },
 
+    // Retrieves a server by tag.
+    { MySqlConfigBackendDHCPv6Impl::GET_SERVER6,
+      MYSQL_GET_SERVER(dhcp6)
+    },
+
+    // Retrieves all servers.
+    { MySqlConfigBackendDHCPv6Impl::GET_ALL_SERVERS6,
+      MYSQL_GET_ALL_SERVERS(dhcp6)
+    },
+
     // Insert global parameter.
     { MySqlConfigBackendDHCPv6Impl::INSERT_GLOBAL_PARAMETER6,
       MYSQL_INSERT_GLOBAL_PARAMETER(dhcp6)
@@ -2486,6 +2502,11 @@ TaggedStatementArray tagged_statements = { {
       MYSQL_INSERT_OPTION_SERVER(dhcp6)
     },
 
+    // Insert server with server tag and description.
+    { MySqlConfigBackendDHCPv6Impl::INSERT_SERVER6,
+      MYSQL_INSERT_SERVER(dhcp6)
+    },
+
     // Update existing global parameter.
     { MySqlConfigBackendDHCPv6Impl::UPDATE_GLOBAL_PARAMETER6,
       MYSQL_UPDATE_GLOBAL_PARAMETER(dhcp6)
@@ -2575,6 +2596,11 @@ TaggedStatementArray tagged_statements = { {
       MYSQL_UPDATE_OPTION6(AND o.scope_id = 4 AND o.shared_network_name = ? AND o.code = ? AND o.space = ?)
     },
 
+    // Update existing server, e.g. server description.
+    { MySqlConfigBackendDHCPv6Impl::UPDATE_SERVER6,
+      MYSQL_UPDATE_SERVER(dhcp6)
+    },
+
     // Delete global parameter by name.
     { MySqlConfigBackendDHCPv6Impl::DELETE_GLOBAL_PARAMETER6,
       MYSQL_DELETE_GLOBAL_PARAMETER(dhcp6, AND g.name = ?)
@@ -2670,6 +2696,16 @@ TaggedStatementArray tagged_statements = { {
     // Delete options belonging to a shared_network.
     { MySqlConfigBackendDHCPv6Impl::DELETE_OPTIONS6_SHARED_NETWORK,
       MYSQL_DELETE_OPTION(dhcp6, AND o.scope_id = 4 AND o.shared_network_name = ?)
+    },
+
+    // Delete a server by tag.
+    { MySqlConfigBackendDHCPv6Impl::DELETE_SERVER6,
+      MYSQL_DELETE_SERVER(dhcp6)
+    },
+
+    // Deletes all servers except logical server 'all'.
+    { MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SERVERS6,
+      MYSQL_DELETE_ALL_SERVERS(dhcp6)
     }
 }
 };
@@ -2894,14 +2930,22 @@ MySqlConfigBackendDHCPv6::getRecentAuditEntries(const db::ServerSelector& server
 
 ServerCollection
 MySqlConfigBackendDHCPv6::getAllServers6() const {
-    isc_throw(NotImplemented, "MySqlConfigBackendDHCPv6::getAllServers6"
-              " is not implemented");
+    ServerCollection servers;
+
+    LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_ALL_SERVERS6);
+    impl_->getAllServers(MySqlConfigBackendDHCPv6Impl::GET_ALL_SERVERS6,
+                         servers);
+
+    LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_ALL_SERVERS6_RESULT)
+        .arg(servers.size());
+    return (servers);
 }
 
 ServerPtr
-MySqlConfigBackendDHCPv6::getServer6(const data::ServerTag& /* server_tag */) const {
-    isc_throw(NotImplemented, "MySqlConfigBackendDHCPv6::getServer6"
-              " is not implemented");
+MySqlConfigBackendDHCPv6::getServer6(const data::ServerTag& server_tag) const {
+    LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_SERVER6)
+        .arg(server_tag.get());
+    return (impl_->getServer(MySqlConfigBackendDHCPv6Impl::GET_SERVER6, server_tag));
 }
 
 void
@@ -2984,9 +3028,13 @@ MySqlConfigBackendDHCPv6::createUpdateGlobalParameter6(const ServerSelector& ser
 }
 
 void
-MySqlConfigBackendDHCPv6::createUpdateServer6(const ServerPtr& /* server */) {
-    isc_throw(NotImplemented, "MySqlConfigBackendDHCPv6::createUpdateServer6"
-              " is not implemented");
+MySqlConfigBackendDHCPv6::createUpdateServer6(const ServerPtr& server) {
+    LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_CREATE_UPDATE_SERVER6)
+        .arg(server->getServerTag());
+    impl_->createUpdateServer(MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
+                              MySqlConfigBackendDHCPv6Impl::INSERT_SERVER6,
+                              MySqlConfigBackendDHCPv6Impl::UPDATE_SERVER6,
+                              server);
 }
 
 uint64_t
@@ -3180,15 +3228,18 @@ MySqlConfigBackendDHCPv6::deleteAllGlobalParameters6(const ServerSelector& serve
 }
 
 uint64_t
-MySqlConfigBackendDHCPv6::deleteServer6(const std::string& /* server_tag */) {
-    isc_throw(NotImplemented, "MySqlConfigBackendDHCPv4::deleteServer6"
-              " is not implemented");
+MySqlConfigBackendDHCPv6::deleteServer6(const ServerTag& server_tag) {
+    uint64_t result = impl_->deleteServer(MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
+                                          MySqlConfigBackendDHCPv6Impl::DELETE_SERVER6,
+                                          server_tag.get());
+    return (result);
 }
 
 uint64_t
 MySqlConfigBackendDHCPv6::deleteAllServers6() {
-    isc_throw(NotImplemented, "MySqlConfigBackendDHCPv6::deleteAllServers6"
-              " is not implemented");
+    uint64_t result = impl_->deleteAllServers(MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
+                                              MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SERVERS6);
+    return (result);
 }
 
 std::string
index e395d6e122371c040c74248d09e76f088bc635c9..b51fe722a1336fca14ffb9733a53097b6428ae1b 100644 (file)
@@ -483,7 +483,7 @@ public:
     /// @param server_tag Tag of the server to be deleted.
     /// @return Number of deleted servers.
     virtual uint64_t
-    deleteServer6(const std::string& server_tag);
+    deleteServer6(const data::ServerTag& server_tag);
 
     /// @brief Deletes all servers from the backend except the logical
     /// server 'all'.
index 741f9862b494ee11f5dda895c8ac88979ee0c31a..f606a71ac92e63c8c134864ae7f303f00ff9d8dd 100644 (file)
@@ -832,6 +832,136 @@ MySqlConfigBackendImpl::createOptionValueBinding(const OptionDescriptorPtr& opti
     return (MySqlBinding::createNull());
 }
 
+ServerPtr
+MySqlConfigBackendImpl::getServer(const int index, const ServerTag& server_tag) {
+    ServerCollection servers;
+    MySqlBindingCollection in_bindings = {
+        MySqlBinding::createString(server_tag.get())
+    };
+    getServers(index, in_bindings, servers);
+
+    return (servers.empty() ? ServerPtr() : *servers.begin());
+}
+
+void
+MySqlConfigBackendImpl::getAllServers(const int index, db::ServerCollection& servers) {
+    MySqlBindingCollection in_bindings;
+    getServers(index, in_bindings, servers);
+}
+
+void
+MySqlConfigBackendImpl::getServers(const int index,
+                                   const MySqlBindingCollection& in_bindings,
+                                   ServerCollection& servers) {
+    MySqlBindingCollection out_bindings = {
+        MySqlBinding::createInteger<uint64_t>(),
+        MySqlBinding::createString(SERVER_TAG_BUF_LENGTH),
+        MySqlBinding::createString(SERVER_DESCRIPTION_BUF_LENGTH),
+        MySqlBinding::createTimestamp()
+    };
+
+    conn_.selectQuery(index, in_bindings, out_bindings,
+                      [&servers](MySqlBindingCollection& out_bindings) {
+
+        ServerPtr last_server;
+        uint64_t id = out_bindings[0]->getInteger<uint64_t>();
+        if (!last_server || (last_server->getId() != id)) {
+
+            // Set description if it is non-null.
+            auto desc = (out_bindings[2]->amNull() ? "" : out_bindings[2]->getString());
+            last_server = Server::create(ServerTag(out_bindings[1]->getString()),
+                                         desc);
+
+            // id
+            last_server->setId(id);
+
+            // modification_ts
+            last_server->setModificationTime(out_bindings[3]->getTimestamp());
+
+            // New server fetched. Let's store it.
+            servers.insert(last_server);
+        }
+    });
+}
+
+void
+MySqlConfigBackendImpl::createUpdateServer(const int create_audit_revision_index,
+                                           const int create_index,
+                                           const int update_index,
+                                           const ServerPtr& server) {
+    // Create scoped audit revision. As long as this instance exists
+    // no new audit revisions are created in any subsequent calls.
+    ScopedAuditRevision audit_revision(this,
+                                       create_audit_revision_index,
+                                       ServerSelector::ALL(),
+                                       "server set",
+                                       true);
+
+    MySqlTransaction transaction(conn_);
+
+    MySqlBindingCollection in_bindings = {
+        MySqlBinding::createString(server->getServerTag()),
+        MySqlBinding::createString(server->getDescription()),
+        MySqlBinding::createTimestamp(server->getModificationTime())
+    };
+
+    try {
+        conn_.insertQuery(create_index, in_bindings);
+
+    } catch (const DuplicateEntry&) {
+        in_bindings.push_back(MySqlBinding::createString(server->getServerTag()));
+        conn_.updateDeleteQuery(update_index, in_bindings);
+    }
+
+    transaction.commit();
+}
+
+uint64_t
+MySqlConfigBackendImpl::deleteServer(const int create_audit_revision_index,
+                                     const int delete_index,
+                                     const std::string& server_tag) {
+
+    MySqlTransaction transaction(conn_);
+
+    // Create scoped audit revision. As long as this instance exists
+    // no new audit revisions are created in any subsequent calls.
+    ScopedAuditRevision
+        audit_revision(this, create_audit_revision_index,
+                       ServerSelector::ALL(), "deleting a server", false);
+
+    // Specify which server should be deleted.
+    MySqlBindingCollection in_bindings = {
+        MySqlBinding::createString(server_tag)
+    };
+
+    // Attempt to delete the server.
+    auto count = conn_.updateDeleteQuery(delete_index, in_bindings);
+    transaction.commit();
+
+    return (count);
+}
+
+uint64_t
+MySqlConfigBackendImpl::deleteAllServers(const int create_audit_revision_index,
+                                         const int delete_index) {
+
+    MySqlTransaction transaction(conn_);
+
+    // Create scoped audit revision. As long as this instance exists
+    // no new audit revisions are created in any subsequent calls.
+    ScopedAuditRevision
+        audit_revision(this, create_audit_revision_index,
+                       ServerSelector::ALL(), "deleting a server", false);
+
+    MySqlBindingCollection in_bindings;
+
+    // Attempt to delete the servers.
+    auto count = conn_.updateDeleteQuery(delete_index, in_bindings);
+    transaction.commit();
+
+    return (count);
+}
+
 std::string
 MySqlConfigBackendImpl::getType() const {
     return ("mysql");
index 1a3392d7aa6510e1096c68acf59df1fe74f5f153..889c5893893a77d2776d45a65e5e9294b63ff58b 100644 (file)
@@ -10,6 +10,8 @@
 #include <cc/stamped_value.h>
 #include <database/audit_entry.h>
 #include <database/database_connection.h>
+#include <database/server.h>
+#include <database/server_collection.h>
 #include <database/server_selector.h>
 #include <dhcp/option.h>
 #include <dhcp/option_definition.h>
@@ -340,7 +342,7 @@ public:
     /// 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] subnets Reference to the container where fetched parameters
+    /// @param [out] parameters Reference to the container where fetched parameters
     /// will be inserted.
     void getGlobalParameters(const int index,
                              const db::MySqlBindingCollection& in_bindings,
@@ -595,6 +597,79 @@ public:
                 db::MySqlBinding::createNull());
     }
 
+    /// @brief Creates input binding for option value parameter.
+    ///
+    /// @param option Option descriptor holding option for which binding is to
+    /// be created.
+    /// @return Pointer to the binding (possibly null binding if formatted
+    /// value is non-empty.
+    db::MySqlBindingPtr createOptionValueBinding(const OptionDescriptorPtr& option);
+
+    /// @brief Retrieves a server.
+    ///
+    /// @param index Index of the query to be used.
+    /// @param server_tag Server tag of the server to be retrieved.
+    /// @return Pointer to the @c Server object representing the server or
+    /// null if such server doesn't exist.
+    db::ServerPtr getServer(const int index, const data::ServerTag& server_tag);
+
+    /// @brief Retrieves all servers.
+    ///
+    /// @param index Index of the query to be used.
+    /// @param [out] servers Reference to the container where fetched servers
+    /// will be inserted.
+    void getAllServers(const int index, db::ServerCollection& servers);
+
+    /// @brief Sends query to retrieve servers.
+    ///
+    /// @param index Index of the query to be used.
+    /// @param in_bindings Reference to the MySQL input bindings.
+    /// @param [out] servers Reference to the container where fetched servers
+    /// will be inserted.
+    void getServers(const int index,
+                    const db::MySqlBindingCollection& in_bindings,
+                    db::ServerCollection& servers);
+
+    /// @brief Creates or updates a server.
+    ///
+    /// This method attempts to insert a new server into the database using
+    /// the query identified by @c create_index. If the insertion fails because
+    /// the server with the given tag already exists in the database, the
+    /// existing server is updated using the query identified by the
+    /// @c update_index.
+    ///
+    /// @param create_audit_revision Index of the query inserting audit
+    /// revision.
+    /// @param create_index Index of the INSERT query to be used.
+    /// @param update_index index of the UPDATE query to be used.
+    /// @param server Pointer to the server to be insertedor updated.
+    void createUpdateServer(const int create_audit_revision_index,
+                            const int create_index,
+                            const int update_index,
+                            const db::ServerPtr& server);
+
+    /// @brief Attempts to delete a server having a given tag.
+    ///
+    /// @param create_audit_revision Index of the query inserting audit
+    /// revision.
+    /// @param create_index Index of the DELETE query to be executed.
+    /// @param server_tag Tag of the server to be deleted.
+    /// @return Number of deleted servers.
+    uint64_t deleteServer(const int create_audit_revision_index, const int index,
+                          const std::string& server_tag);
+
+    /// @brief Attempts to delete all servers.
+    ///
+    /// This method deletes all servers added by the user. It does not
+    /// delete the logical server 'all'.
+    ///
+    /// @param create_audit_revision Index of the query inserting audit
+    /// revision.
+    /// @param server_tag Tag of the server to be deleted.
+    /// @return Number of deleted servers.
+    uint64_t deleteAllServers(const int create_audit_revision_index,
+                              const int index);
+
     /// @brief Returns backend type in the textual format.
     ///
     /// @return "mysql".
@@ -616,14 +691,6 @@ public:
     /// @return Port number on which database service is available.
     uint16_t getPort() const;
 
-    /// @brief Creates input binding for option value parameter.
-    ///
-    /// @param option Option descriptor holding option for which binding is to
-    /// be created.
-    /// @return Pointer to the binding (possibly null binding if formatted
-    /// value is non-empty.
-    db::MySqlBindingPtr createOptionValueBinding(const OptionDescriptorPtr& option);
-
     /// @brief Represents connection to the MySQL database.
     db::MySqlConnection conn_;
 
index 8c2d8a93300774f80dd4d883ce6defb9b6c9563a..cf84ea6f06e8f243115676f6ac98e3b4947cac8f 100644 (file)
@@ -1,4 +1,4 @@
-// File created from ../../../../src/hooks/dhcp/mysql_cb/mysql_cb_messages.mes on Thu May 16 2019 15:00
+// File created from ../../../../src/hooks/dhcp/mysql_cb/mysql_cb_messages.mes on Wed Jun 12 2019 14:09
 
 #include <cstddef>
 #include <log/message_types.h>
@@ -18,6 +18,8 @@ extern const isc::log::MessageID MYSQL_CB_CREATE_UPDATE_OPTION4 = "MYSQL_CB_CREA
 extern const isc::log::MessageID MYSQL_CB_CREATE_UPDATE_OPTION6 = "MYSQL_CB_CREATE_UPDATE_OPTION6";
 extern const isc::log::MessageID MYSQL_CB_CREATE_UPDATE_OPTION_DEF4 = "MYSQL_CB_CREATE_UPDATE_OPTION_DEF4";
 extern const isc::log::MessageID MYSQL_CB_CREATE_UPDATE_OPTION_DEF6 = "MYSQL_CB_CREATE_UPDATE_OPTION_DEF6";
+extern const isc::log::MessageID MYSQL_CB_CREATE_UPDATE_SERVER4 = "MYSQL_CB_CREATE_UPDATE_SERVER4";
+extern const isc::log::MessageID MYSQL_CB_CREATE_UPDATE_SERVER6 = "MYSQL_CB_CREATE_UPDATE_SERVER6";
 extern const isc::log::MessageID MYSQL_CB_CREATE_UPDATE_SHARED_NETWORK4 = "MYSQL_CB_CREATE_UPDATE_SHARED_NETWORK4";
 extern const isc::log::MessageID MYSQL_CB_CREATE_UPDATE_SHARED_NETWORK6 = "MYSQL_CB_CREATE_UPDATE_SHARED_NETWORK6";
 extern const isc::log::MessageID MYSQL_CB_CREATE_UPDATE_SHARED_NETWORK_OPTION4 = "MYSQL_CB_CREATE_UPDATE_SHARED_NETWORK_OPTION4";
@@ -95,6 +97,10 @@ extern const isc::log::MessageID MYSQL_CB_GET_ALL_OPTION_DEFS4 = "MYSQL_CB_GET_A
 extern const isc::log::MessageID MYSQL_CB_GET_ALL_OPTION_DEFS4_RESULT = "MYSQL_CB_GET_ALL_OPTION_DEFS4_RESULT";
 extern const isc::log::MessageID MYSQL_CB_GET_ALL_OPTION_DEFS6 = "MYSQL_CB_GET_ALL_OPTION_DEFS6";
 extern const isc::log::MessageID MYSQL_CB_GET_ALL_OPTION_DEFS6_RESULT = "MYSQL_CB_GET_ALL_OPTION_DEFS6_RESULT";
+extern const isc::log::MessageID MYSQL_CB_GET_ALL_SERVERS4 = "MYSQL_CB_GET_ALL_SERVERS4";
+extern const isc::log::MessageID MYSQL_CB_GET_ALL_SERVERS4_RESULT = "MYSQL_CB_GET_ALL_SERVERS4_RESULT";
+extern const isc::log::MessageID MYSQL_CB_GET_ALL_SERVERS6 = "MYSQL_CB_GET_ALL_SERVERS6";
+extern const isc::log::MessageID MYSQL_CB_GET_ALL_SERVERS6_RESULT = "MYSQL_CB_GET_ALL_SERVERS6_RESULT";
 extern const isc::log::MessageID MYSQL_CB_GET_ALL_SHARED_NETWORKS4 = "MYSQL_CB_GET_ALL_SHARED_NETWORKS4";
 extern const isc::log::MessageID MYSQL_CB_GET_ALL_SHARED_NETWORKS4_RESULT = "MYSQL_CB_GET_ALL_SHARED_NETWORKS4_RESULT";
 extern const isc::log::MessageID MYSQL_CB_GET_ALL_SHARED_NETWORKS6 = "MYSQL_CB_GET_ALL_SHARED_NETWORKS6";
@@ -137,6 +143,8 @@ extern const isc::log::MessageID MYSQL_CB_GET_RECENT_AUDIT_ENTRIES4 = "MYSQL_CB_
 extern const isc::log::MessageID MYSQL_CB_GET_RECENT_AUDIT_ENTRIES4_RESULT = "MYSQL_CB_GET_RECENT_AUDIT_ENTRIES4_RESULT";
 extern const isc::log::MessageID MYSQL_CB_GET_RECENT_AUDIT_ENTRIES6 = "MYSQL_CB_GET_RECENT_AUDIT_ENTRIES6";
 extern const isc::log::MessageID MYSQL_CB_GET_RECENT_AUDIT_ENTRIES6_RESULT = "MYSQL_CB_GET_RECENT_AUDIT_ENTRIES6_RESULT";
+extern const isc::log::MessageID MYSQL_CB_GET_SERVER4 = "MYSQL_CB_GET_SERVER4";
+extern const isc::log::MessageID MYSQL_CB_GET_SERVER6 = "MYSQL_CB_GET_SERVER6";
 extern const isc::log::MessageID MYSQL_CB_GET_SHARED_NETWORK4 = "MYSQL_CB_GET_SHARED_NETWORK4";
 extern const isc::log::MessageID MYSQL_CB_GET_SHARED_NETWORK6 = "MYSQL_CB_GET_SHARED_NETWORK6";
 extern const isc::log::MessageID MYSQL_CB_GET_SHARED_NETWORK_SUBNETS4 = "MYSQL_CB_GET_SHARED_NETWORK_SUBNETS4";
@@ -172,6 +180,8 @@ const char* values[] = {
     "MYSQL_CB_CREATE_UPDATE_OPTION6", "create or update option",
     "MYSQL_CB_CREATE_UPDATE_OPTION_DEF4", "create or update option definition: %1 code: %2",
     "MYSQL_CB_CREATE_UPDATE_OPTION_DEF6", "create or update option definition: %1 code: %2",
+    "MYSQL_CB_CREATE_UPDATE_SERVER4", "create or update server: %1",
+    "MYSQL_CB_CREATE_UPDATE_SERVER6", "create or update server: %1",
     "MYSQL_CB_CREATE_UPDATE_SHARED_NETWORK4", "create or update shared network: %1",
     "MYSQL_CB_CREATE_UPDATE_SHARED_NETWORK6", "create or update shared network: %1",
     "MYSQL_CB_CREATE_UPDATE_SHARED_NETWORK_OPTION4", "create or update shared network: %1 option",
@@ -249,6 +259,10 @@ const char* values[] = {
     "MYSQL_CB_GET_ALL_OPTION_DEFS4_RESULT", "retrieving: %1 elements",
     "MYSQL_CB_GET_ALL_OPTION_DEFS6", "retrieving all option definitions",
     "MYSQL_CB_GET_ALL_OPTION_DEFS6_RESULT", "retrieving: %1 elements",
+    "MYSQL_CB_GET_ALL_SERVERS4", "retrieving all servers",
+    "MYSQL_CB_GET_ALL_SERVERS4_RESULT", "retrieving: %1 elements",
+    "MYSQL_CB_GET_ALL_SERVERS6", "retrieving all DHCPv6 servers",
+    "MYSQL_CB_GET_ALL_SERVERS6_RESULT", "retrieving: %1 elements",
     "MYSQL_CB_GET_ALL_SHARED_NETWORKS4", "retrieving all shared networks",
     "MYSQL_CB_GET_ALL_SHARED_NETWORKS4_RESULT", "retrieving: %1 elements",
     "MYSQL_CB_GET_ALL_SHARED_NETWORKS6", "retrieving all shared networks",
@@ -291,6 +305,8 @@ const char* values[] = {
     "MYSQL_CB_GET_RECENT_AUDIT_ENTRIES4_RESULT", "retrieving: %1 elements",
     "MYSQL_CB_GET_RECENT_AUDIT_ENTRIES6", "retrieving audit entries from: %1",
     "MYSQL_CB_GET_RECENT_AUDIT_ENTRIES6_RESULT", "retrieving: %1 elements",
+    "MYSQL_CB_GET_SERVER4", "retrieving DHCPv4 server: %1",
+    "MYSQL_CB_GET_SERVER6", "retrieving DHCPv6 server: %1",
     "MYSQL_CB_GET_SHARED_NETWORK4", "retrieving shared network: %1",
     "MYSQL_CB_GET_SHARED_NETWORK6", "retrieving shared network: %1",
     "MYSQL_CB_GET_SHARED_NETWORK_SUBNETS4", "retrieving shared network: %1 subnets",
index 579ce9d75851f5914a0d98edde8f20c51b2f70f6..34334eec92bcebab6fcb2d3b29c6ce07dab828e1 100644 (file)
@@ -1,4 +1,4 @@
-// File created from ../../../../src/hooks/dhcp/mysql_cb/mysql_cb_messages.mes on Thu May 16 2019 15:00
+// File created from ../../../../src/hooks/dhcp/mysql_cb/mysql_cb_messages.mes on Wed Jun 12 2019 14:09
 
 #ifndef MYSQL_CB_MESSAGES_H
 #define MYSQL_CB_MESSAGES_H
@@ -19,6 +19,8 @@ extern const isc::log::MessageID MYSQL_CB_CREATE_UPDATE_OPTION4;
 extern const isc::log::MessageID MYSQL_CB_CREATE_UPDATE_OPTION6;
 extern const isc::log::MessageID MYSQL_CB_CREATE_UPDATE_OPTION_DEF4;
 extern const isc::log::MessageID MYSQL_CB_CREATE_UPDATE_OPTION_DEF6;
+extern const isc::log::MessageID MYSQL_CB_CREATE_UPDATE_SERVER4;
+extern const isc::log::MessageID MYSQL_CB_CREATE_UPDATE_SERVER6;
 extern const isc::log::MessageID MYSQL_CB_CREATE_UPDATE_SHARED_NETWORK4;
 extern const isc::log::MessageID MYSQL_CB_CREATE_UPDATE_SHARED_NETWORK6;
 extern const isc::log::MessageID MYSQL_CB_CREATE_UPDATE_SHARED_NETWORK_OPTION4;
@@ -96,6 +98,10 @@ extern const isc::log::MessageID MYSQL_CB_GET_ALL_OPTION_DEFS4;
 extern const isc::log::MessageID MYSQL_CB_GET_ALL_OPTION_DEFS4_RESULT;
 extern const isc::log::MessageID MYSQL_CB_GET_ALL_OPTION_DEFS6;
 extern const isc::log::MessageID MYSQL_CB_GET_ALL_OPTION_DEFS6_RESULT;
+extern const isc::log::MessageID MYSQL_CB_GET_ALL_SERVERS4;
+extern const isc::log::MessageID MYSQL_CB_GET_ALL_SERVERS4_RESULT;
+extern const isc::log::MessageID MYSQL_CB_GET_ALL_SERVERS6;
+extern const isc::log::MessageID MYSQL_CB_GET_ALL_SERVERS6_RESULT;
 extern const isc::log::MessageID MYSQL_CB_GET_ALL_SHARED_NETWORKS4;
 extern const isc::log::MessageID MYSQL_CB_GET_ALL_SHARED_NETWORKS4_RESULT;
 extern const isc::log::MessageID MYSQL_CB_GET_ALL_SHARED_NETWORKS6;
@@ -138,6 +144,8 @@ extern const isc::log::MessageID MYSQL_CB_GET_RECENT_AUDIT_ENTRIES4;
 extern const isc::log::MessageID MYSQL_CB_GET_RECENT_AUDIT_ENTRIES4_RESULT;
 extern const isc::log::MessageID MYSQL_CB_GET_RECENT_AUDIT_ENTRIES6;
 extern const isc::log::MessageID MYSQL_CB_GET_RECENT_AUDIT_ENTRIES6_RESULT;
+extern const isc::log::MessageID MYSQL_CB_GET_SERVER4;
+extern const isc::log::MessageID MYSQL_CB_GET_SERVER6;
 extern const isc::log::MessageID MYSQL_CB_GET_SHARED_NETWORK4;
 extern const isc::log::MessageID MYSQL_CB_GET_SHARED_NETWORK6;
 extern const isc::log::MessageID MYSQL_CB_GET_SHARED_NETWORK_SUBNETS4;
index 522f81f95fb903cf7e4d0dfdda0be19f452b112e..3dd58b32ac82a0cd02b71743c5b911461e582aa5 100644 (file)
@@ -53,6 +53,14 @@ Debug message issued when triggered an action to create or update subnet
 % MYSQL_CB_CREATE_UPDATE_SUBNET6 create or update subnet: %1
 Debug message issued when triggered an action to create or update subnet
 
+% MYSQL_CB_CREATE_UPDATE_SERVER4 create or update server: %1
+Debug message issued when triggered an action to create or update a DHCPv4
+server information.
+
+% MYSQL_CB_CREATE_UPDATE_SERVER6 create or update server: %1
+Debug message issued when triggered an action to create or update a DHCPv6
+server information.
+
 % MYSQL_CB_DEINIT_OK unloading MYSQAL CB hooks library successful
 This informational message indicates that the MySQL Configuration Backend hooks
 library has been unloaded successfully.
@@ -267,6 +275,22 @@ Debug message issued when triggered an action to retrieve all option definitions
 % MYSQL_CB_GET_ALL_OPTION_DEFS6_RESULT retrieving: %1 elements
 Debug message indicating the result of an action to retrieve all option definitions
 
+% MYSQL_CB_GET_ALL_SERVERS4 retrieving all servers
+Debug message issued when triggered an action to retrieve all DHCPv4
+servers
+
+% MYSQL_CB_GET_ALL_SERVERS4_RESULT retrieving: %1 elements
+Debug message indicating the result of an action to retrieve all DHCPv4
+servers
+
+% MYSQL_CB_GET_ALL_SERVERS6 retrieving all DHCPv6 servers
+Debug message issued when triggered an action to retrieve all DHCPv6
+servers
+
+% MYSQL_CB_GET_ALL_SERVERS6_RESULT retrieving: %1 elements
+Debug message indicating the result of an action to retrieve all DHCPv6
+servers
+
 % MYSQL_CB_GET_ALL_SHARED_NETWORKS4 retrieving all shared networks
 Debug message issued when triggered an action to retrieve all shared networks
 
@@ -393,6 +417,12 @@ Debug message issued when triggered an action to retrieve audit entries from spe
 % MYSQL_CB_GET_RECENT_AUDIT_ENTRIES6_RESULT retrieving: %1 elements
 Debug message indicating the result of an action to retrieve audit entries from specified time
 
+% MYSQL_CB_GET_SERVER4 retrieving DHCPv4 server: %1
+Debug message issued when triggered an action to retrieve a DHCPv4 server information.
+
+% MYSQL_CB_GET_SERVER6 retrieving DHCPv6 server: %1
+Debug message issued when triggered an action to retrieve a DHCPv6 server information.
+
 % MYSQL_CB_GET_SHARED_NETWORK4 retrieving shared network: %1
 Debug message issued when triggered an action to retrieve shared network
 
index a38a6c8e19c420acff76f93ac7a246319a1094f4..b6f9e86ee78a991e0b48c9c452a17ecb556bcf47 100644 (file)
@@ -379,6 +379,23 @@ namespace {
     "ORDER BY r.modification_ts, r.id"
 #endif
 
+#ifndef MYSQL_GET_SERVERS_COMMON
+#define MYSQL_GET_SERVERS_COMMON(table_prefix, ...) \
+    "SELECT" \
+    "  s.id," \
+    "  s.tag," \
+    "  s.description," \
+    "  s.modification_ts " \
+    "FROM " #table_prefix "_server AS s " \
+    "WHERE s.id > 1 " \
+    __VA_ARGS__ \
+    "ORDER BY s.id"
+#define MYSQL_GET_ALL_SERVERS(table_prefix) \
+    MYSQL_GET_SERVERS_COMMON(table_prefix, "")
+#define MYSQL_GET_SERVER(table_prefix) \
+    MYSQL_GET_SERVERS_COMMON(table_prefix, "AND s.tag = ? ")
+#endif
+
 #ifndef MYSQL_INSERT_GLOBAL_PARAMETER
 #define MYSQL_INSERT_GLOBAL_PARAMETER(table_prefix) \
     "INSERT INTO " #table_prefix "_global_parameter(" \
@@ -497,6 +514,15 @@ namespace {
     ") VALUES (?, (SELECT id FROM " #table_prefix "_server WHERE tag = ?), ?)"
 #endif
 
+#ifndef MYSQL_INSERT_SERVER
+#define MYSQL_INSERT_SERVER(table_prefix) \
+    "INSERT INTO " #table_prefix "_server (" \
+    "  tag," \
+    "  description," \
+    "  modification_ts" \
+    ") VALUES (?, ?, ?)"
+#endif
+
 #ifndef MYSQL_UPDATE_GLOBAL_PARAMETER
 #define MYSQL_UPDATE_GLOBAL_PARAMETER(table_prefix) \
     "UPDATE " #table_prefix "_global_parameter AS g " \
@@ -561,6 +587,16 @@ namespace {
     MYSQL_UPDATE_OPTION_COMMON(dhcp6, ", o.pd_pool_id = ? ", __VA_ARGS__)
 #endif
 
+#ifndef MYSQL_UPDATE_SERVER
+#define MYSQL_UPDATE_SERVER(table_prefix) \
+    "UPDATE " #table_prefix "_server " \
+    "SET" \
+    "  tag = ?," \
+    "  description = ?," \
+    "  modification_ts = ? " \
+    "WHERE tag = ?"
+#endif
+
 #ifndef MYSQL_DELETE_GLOBAL_PARAMETER
 #define MYSQL_DELETE_GLOBAL_PARAMETER(table_prefix, ...) \
     "DELETE g FROM " #table_prefix "_global_parameter AS g " \
@@ -649,6 +685,18 @@ namespace {
     "   WHERE prefix = ? AND prefix_length = ?)"
 #endif
 
+#ifndef MYSQL_DELETE_SERVER
+#define MYSQL_DELETE_SERVER(table_prefix) \
+    "DELETE FROM " #table_prefix "_server " \
+    "WHERE tag = ?"
+#endif
+
+#ifndef MYSQL_DELETE_ALL_SERVERS
+#define MYSQL_DELETE_ALL_SERVERS(table_prefix) \
+    "DELETE FROM " #table_prefix "_server " \
+    "WHERE id > 1"
+#endif
+
 } // end of anonymous namespace
 
 } // end of namespace isc::dhcp
index be09ab75d0fac09704f8120a685c6c7f71b347ea..88dace1cc4d61524ce25a607005ac5dc8b14829a 100644 (file)
@@ -7,6 +7,7 @@
 #include <config.h>
 #include <mysql_cb_dhcp4.h>
 #include <database/db_exceptions.h>
+#include <database/server.h>
 #include <database/testutils/schema.h>
 #include <dhcp/dhcp6.h>
 #include <dhcp/libdhcp++.h>
@@ -47,7 +48,9 @@ public:
 
     /// @brief Constructor.
     MySqlConfigBackendDHCPv4Test()
-        : test_subnets_(), test_networks_(), timestamps_(), audit_entries_() {
+        : 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.
         createMySQLSchema();
 
@@ -67,6 +70,7 @@ public:
         }
 
         // Create test data.
+        initTestServers();
         initTestOptions();
         initTestSubnets();
         initTestSharedNetworks();
@@ -81,6 +85,14 @@ public:
         destroyMySQLSchema();
     }
 
+    /// @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.
@@ -394,6 +406,9 @@ public:
     /// @brief Holds pointers to options used in tests.
     std::vector<OptionDescriptorPtr> test_options_;
 
+    /// @brief Holds pointers to the servers used in tests.
+    std::vector<ServerPtr> test_servers_;
+
     /// @brief Holds timestamp values used in tests.
     std::map<std::string, boost::posix_time::ptime> timestamps_;
 
@@ -436,6 +451,115 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getPort) {
     EXPECT_EQ(0, cbptr_->getPort());
 }
 
+// This test verifies that the server can be added, updated and deleted.
+TEST_F(MySqlConfigBackendDHCPv4Test, 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_->createUpdateServer4(test_servers_[0]));
+
+    {
+        SCOPED_TRACE("CREATE audit entry for server");
+        testNewAuditEntry("dhcp4_server",
+                          AuditEntry::ModificationType::CREATE,
+                          "server set");
+    }
+
+    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_->getServer4(ServerTag("server2")));
+    EXPECT_FALSE(returned_server);
+
+    // Try to fetch the server which we expect to exist.
+    EXPECT_NO_THROW(returned_server = cbptr_->getServer4(ServerTag("server1")));
+    ASSERT_TRUE(returned_server);
+    EXPECT_EQ("server1", returned_server->getServerTag());
+    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_->createUpdateServer4(test_servers_[1]));
+
+    {
+        SCOPED_TRACE("UPDATE audit entry for server");
+        testNewAuditEntry("dhcp4_server",
+                          AuditEntry::ModificationType::UPDATE,
+                          "server set");
+    }
+
+    // Verify that the server has been updated. 
+    EXPECT_NO_THROW(returned_server = cbptr_->getServer4(ServerTag("server1")));
+    ASSERT_TRUE(returned_server);
+    EXPECT_EQ("server1", returned_server->getServerTag());
+    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_->deleteServer4(ServerTag("server2")));
+    EXPECT_EQ(0, servers_deleted);
+
+
+    // Delete the existing server.
+    EXPECT_NO_THROW(servers_deleted = cbptr_->deleteServer4(ServerTag("server1")));
+    EXPECT_EQ(1, servers_deleted);
+
+    {
+        SCOPED_TRACE("DELETE audit entry for server");
+        testNewAuditEntry("dhcp4_server",
+                          AuditEntry::ModificationType::DELETE,
+                          "deleting a server");
+    }
+
+    // Make sure that the server is gone.
+    EXPECT_NO_THROW(returned_server = cbptr_->getServer4(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(MySqlConfigBackendDHCPv4Test, getAndDeleteAllServers) {
+    for (auto i = 1; i < test_servers_.size(); ++i) {
+        EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[i]));
+    }
+
+    ServerCollection servers;
+    EXPECT_NO_THROW(servers = cbptr_->getAllServers4());
+    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_->deleteAllServers4());
+
+    EXPECT_NO_THROW(servers = cbptr_->getAllServers4());
+    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(MySqlConfigBackendDHCPv4Test, createUpdateDeleteGlobalParameter4) {
index 0da4776b70581d2affa6b3ca4b06ede32c554480..9c76c0505034cde97d9f3cc7c9ddc13f183d6da9 100644 (file)
@@ -48,7 +48,9 @@ public:
 
     /// @brief Constructor.
     MySqlConfigBackendDHCPv6Test()
-        : test_subnets_(), test_networks_(), timestamps_(), audit_entries_() {
+        : 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.
         createMySQLSchema();
 
@@ -68,6 +70,7 @@ public:
         }
 
         // Create test data.
+        initTestServers();
         initTestOptions();
         initTestSubnets();
         initTestSharedNetworks();
@@ -82,6 +85,14 @@ public:
         destroyMySQLSchema();
     }
 
+    /// @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.
@@ -436,6 +447,9 @@ public:
     /// @brief Holds pointers to options used in tests.
     std::vector<OptionDescriptorPtr> test_options_;
 
+    /// @brief Holds pointers to the servers used in tests.
+    std::vector<ServerPtr> test_servers_;
+
     /// @brief Holds timestamp values used in tests.
     std::map<std::string, boost::posix_time::ptime> timestamps_;
 
@@ -478,6 +492,115 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getPort) {
     EXPECT_EQ(0, cbptr_->getPort());
 }
 
+// This test verifies that the server can be added, updated and deleted.
+TEST_F(MySqlConfigBackendDHCPv6Test, 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");
+    }
+
+    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->getServerTag());
+    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());
+    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);
+
+
+    // 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(MySqlConfigBackendDHCPv6Test, 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(MySqlConfigBackendDHCPv6Test, createUpdateDeleteGlobalParameter6) {
index 81a6307436a2faf936fd044e3ad9469de6e3ea94..6cabd5aa7aa5ce90b4c03d49fba403bfb185d352 100644 (file)
@@ -68,6 +68,8 @@ constexpr unsigned long AUDIT_ENTRY_LOG_MESSAGE_BUF_LENGTH = 65536;
 
 constexpr unsigned long SERVER_TAG_BUF_LENGTH = 256;
 
+constexpr unsigned long SERVER_DESCRIPTION_BUF_LENGTH = 65536;
+
 //*}
 
 } // end of namespace isc::cb
index 6f575f8460bb14bbd4d3b0390227e83a0e01bc3b..457193e757cd37441afff611ec75c3b4e39b9e5c 100644 (file)
@@ -434,7 +434,7 @@ public:
     /// @param server_tag Tag of the server to be deleted.
     /// @return Number of deleted servers.
     virtual uint64_t
-    deleteServer4(const std::string& server_tag) = 0;
+    deleteServer4(const data::ServerTag& server_tag) = 0;
 
     /// @brief Deletes all servers from the backend except the logical
     /// server 'all'.
index 61785aa356de8d701fe5b87277d890069b6bcdb5..7e8be2bc156ff8d2176a3829ecbdfdc1670231e3 100644 (file)
@@ -7,6 +7,7 @@
 #ifndef CONFIG_BACKEND_DHCP6_H
 #define CONFIG_BACKEND_DHCP6_H
 
+#include <cc/server_tag.h>
 #include <cc/stamped_value.h>
 #include <config_backend/base_config_backend.h>
 #include <database/audit_entry.h>
@@ -465,7 +466,7 @@ public:
     /// @param server_tag Tag of the server to be deleted.
     /// @return Number of deleted servers.
     virtual uint64_t
-    deleteServer6(const std::string& server_tag) = 0;
+    deleteServer6(const data::ServerTag& server_tag) = 0;
 
     /// @brief Deletes all servers from the backend except the logical
     /// server 'all'.
index ae7024f1364c46679fbdbadedb2554f33912fa11..cf0945202029a6b2ad984fd4b98c0705fda72543 100644 (file)
@@ -448,7 +448,7 @@ ConfigBackendPoolDHCPv4::deleteAllGlobalParameters4(const BackendSelector& backe
 
 uint64_t
 ConfigBackendPoolDHCPv4::deleteServer4(const BackendSelector& backend_selector,
-                                       const std::string& server_tag) {
+                                       const ServerTag& server_tag) {
     return (createUpdateDeleteBackendProperty<uint64_t>
             (&ConfigBackendDHCPv4::deleteServer4, backend_selector,
              server_tag));
index 5aec95dfb5108c899755a97b9b85db6b08446181..973cee42b9766f404fc0283f9682540b457fdbcf 100644 (file)
@@ -523,7 +523,7 @@ public:
     /// @return Number of deleted servers.
     virtual uint64_t
     deleteServer4(const db::BackendSelector& backend_selector,
-                  const std::string& server_tag);
+                  const data::ServerTag& server_tag);
 
     /// @brief Deletes all servers from the backend except the logical
     /// server 'all'.
index eec5501248a47d9582224dd93af3ff3280daa73b..82f9f6c06ebde07f2cf7665e44eb61c4fd29af8a 100644 (file)
@@ -473,7 +473,7 @@ ConfigBackendPoolDHCPv6::deleteAllGlobalParameters6(const BackendSelector& backe
 
 uint64_t
 ConfigBackendPoolDHCPv6::deleteServer6(const BackendSelector& backend_selector,
-                                       const std::string& server_tag) {
+                                       const ServerTag& server_tag) {
     return (createUpdateDeleteBackendProperty<uint64_t>
             (&ConfigBackendDHCPv6::deleteServer6, backend_selector,
              server_tag));
index 820997fc7d718dfdf54d1ede7eea2875348429da..3cf5b6bb40de0b4a06d800c326a6589f4a88fbef 100644 (file)
@@ -7,6 +7,7 @@
 #ifndef CONFIG_BACKEND_POOL_DHCP6_H
 #define CONFIG_BACKEND_POOL_DHCP6_H
 
+#include <cc/server_tag.h>
 #include <cc/stamped_value.h>
 #include <config_backend/base_config_backend_pool.h>
 #include <database/backend_selector.h>
@@ -556,7 +557,7 @@ public:
     /// @return Number of deleted servers.
     virtual uint64_t
     deleteServer6(const db::BackendSelector& backend_selector,
-                  const std::string& server_tag);
+                  const data::ServerTag& server_tag);
 
     /// @brief Deletes all servers from the backend except the logical
     /// server 'all'.
index 863677cc380231e66782fa629301604e6a865877..2c6dda6d7e78808b6b47edb56add5e8c1e52fd56 100644 (file)
@@ -550,9 +550,9 @@ TestConfigBackendDHCPv4::deleteAllGlobalParameters4(const db::ServerSelector& /*
 }
 
 uint64_t
-TestConfigBackendDHCPv4::deleteServer4(const std::string& server_tag) {
+TestConfigBackendDHCPv4::deleteServer4(const ServerTag& server_tag) {
     auto& index = servers_.get<ServerTagIndexTag>();
-    return (index.erase(server_tag));
+    return (index.erase(server_tag.get()));
 }
 
 uint64_t
index 3973452a73775fa8913a9ef586986933e3cbe751..910e2a76eea6a196e519b621e0e741b026a16f14 100644 (file)
@@ -455,7 +455,7 @@ public:
     /// @param server_tag Tag of the server to be deleted.
     /// @return Number of deleted servers.
     virtual uint64_t
-    deleteServer4(const std::string& server_tag);
+    deleteServer4(const data::ServerTag& server_tag);
 
     /// @brief Deletes all servers from the backend except the logical
     /// server 'all'.
index 6f68212a87506ebd29f8104a30394a600c66161d..b5a57ec949e9e68ee680f3a0a5a77335f8de2933 100644 (file)
@@ -587,9 +587,9 @@ TestConfigBackendDHCPv6::deleteAllGlobalParameters6(const db::ServerSelector& /*
 }
 
 uint64_t
-TestConfigBackendDHCPv6::deleteServer6(const std::string& server_tag) {
+TestConfigBackendDHCPv6::deleteServer6(const ServerTag& server_tag) {
     auto& index = servers_.get<ServerTagIndexTag>();
-    return (index.erase(server_tag));
+    return (index.erase(server_tag.get()));
 }
 
 uint64_t
index b0f319f5c7ce2ee0aba98e6e88b1ae5a31dc4404..65410d904c4f65aff926342849ffe1f20abe5dcf 100644 (file)
@@ -486,7 +486,7 @@ public:
     /// @param server_tag Tag of the server to be deleted.
     /// @return Number of deleted servers.
     virtual uint64_t
-    deleteServer6(const std::string& server_tag);
+    deleteServer6(const data::ServerTag& server_tag);
 
     /// @brief Deletes all servers from the backend except the logical
     /// server 'all'.
index a4c0848da89a7d9c02d26636a6314128fb91da5b..d419ae8d55fbb398fcd798815bffb5bc7412dbc4 100644 (file)
@@ -2313,12 +2313,67 @@ ALTER TABLE dhcp6_subnet
     ADD COLUMN min_valid_lifetime INT(10) DEFAULT NULL,
     ADD COLUMN max_valid_lifetime INT(10) DEFAULT NULL;
 
+# Create dhcp4_server insert trigger
+DELIMITER $$
+CREATE TRIGGER dhcp4_server_AINS AFTER INSERT ON dhcp4_server
+    FOR EACH ROW
+    BEGIN
+        CALL createAuditEntryDHCP4('dhcp4_server', NEW.id, "create");
+    END $$
+DELIMITER ;
+
+# Create dhcp4_server update trigger
+DELIMITER $$
+CREATE TRIGGER dhcp4_server_AUPD AFTER UPDATE ON dhcp4_server
+    FOR EACH ROW
+    BEGIN
+        CALL createAuditEntryDHCP4('dhcp4_server', NEW.id, "update");
+    END $$
+DELIMITER ;
+
+# Create dhcp4_server delete trigger
+DELIMITER $$
+CREATE TRIGGER dhcp4_server_ADEL AFTER DELETE ON dhcp4_server
+    FOR EACH ROW
+    BEGIN
+        CALL createAuditEntryDHCP4('dhcp4_server', OLD.id, "delete");
+    END $$
+DELIMITER ;
+
+# Create dhcp6_server insert trigger
+DELIMITER $$
+CREATE TRIGGER dhcp6_server_AINS AFTER INSERT ON dhcp6_server
+    FOR EACH ROW
+    BEGIN
+        CALL createAuditEntryDHCP6('dhcp6_server', NEW.id, "create");
+    END $$
+DELIMITER ;
+
+# Create dhcp6_server update trigger
+DELIMITER $$
+CREATE TRIGGER dhcp6_server_AUPD AFTER UPDATE ON dhcp6_server
+    FOR EACH ROW
+    BEGIN
+        CALL createAuditEntryDHCP6('dhcp6_server', NEW.id, "update");
+    END $$
+DELIMITER ;
+
+# Create dhcp6_server delete trigger
+DELIMITER $$
+CREATE TRIGGER dhcp6_server_ADEL AFTER DELETE ON dhcp6_server
+    FOR EACH ROW
+    BEGIN
+        CALL createAuditEntryDHCP6('dhcp6_server', OLD.id, "delete");
+    END $$
+DELIMITER ;
+
 # Update the schema version number
 UPDATE schema_version
 SET version = '8', minor = '1';
 
 # This line concludes database upgrade to version 8.1.
 
+
 # Notes:
 #
 # Indexes
diff --git a/src/share/database/scripts/mysql/upgrade_8.0_to_9.0.sh.in b/src/share/database/scripts/mysql/upgrade_8.0_to_9.0.sh.in
new file mode 100644 (file)
index 0000000..981ad2a
--- /dev/null
@@ -0,0 +1,84 @@
+#!/bin/sh
+
+# Include utilities. Use installed version if available and
+# use build version if it isn't.
+if [ -e @datarootdir@/@PACKAGE_NAME@/scripts/admin-utils.sh ]; then
+    . @datarootdir@/@PACKAGE_NAME@/scripts/admin-utils.sh
+else
+    . @abs_top_builddir@/src/bin/admin/admin-utils.sh
+fi
+
+VERSION=`mysql_version "$@"`
+
+if [ "$VERSION" != "8.0" ]; then
+    printf "This script upgrades 8.0 to 9.0. Reported version is $VERSION. Skipping upgrade.\n"
+    exit 0
+fi
+
+mysql "$@" <<EOF
+
+# Create dhcp4_server insert trigger
+DELIMITER $$
+CREATE TRIGGER dhcp4_server_AINS AFTER INSERT ON dhcp4_server
+    FOR EACH ROW
+    BEGIN
+        CALL createAuditEntryDHCP4('dhcp4_server', NEW.id, "create");
+    END $$
+DELIMITER ;
+
+# Create dhcp4_server update trigger
+DELIMITER $$
+CREATE TRIGGER dhcp4_server_AUPD AFTER UPDATE ON dhcp4_server
+    FOR EACH ROW
+    BEGIN
+        CALL createAuditEntryDHCP4('dhcp4_server', NEW.id, "update");
+    END $$
+DELIMITER ;
+
+# Create dhcp4_server delete trigger
+DELIMITER $$
+CREATE TRIGGER dhcp4_server_ADEL AFTER DELETE ON dhcp4_server
+    FOR EACH ROW
+    BEGIN
+        CALL createAuditEntryDHCP4('dhcp4_server', OLD.id, "delete");
+    END $$
+DELIMITER ;
+
+# Create dhcp6_server insert trigger
+DELIMITER $$
+CREATE TRIGGER dhcp6_server_AINS AFTER INSERT ON dhcp6_server
+    FOR EACH ROW
+    BEGIN
+        CALL createAuditEntryDHCP6('dhcp6_server', NEW.id, "create");
+    END $$
+DELIMITER ;
+
+# Create dhcp6_server update trigger
+DELIMITER $$
+CREATE TRIGGER dhcp6_server_AUPD AFTER UPDATE ON dhcp6_server
+    FOR EACH ROW
+    BEGIN
+        CALL createAuditEntryDHCP6('dhcp6_server', NEW.id, "update");
+    END $$
+DELIMITER ;
+
+# Create dhcp6_server delete trigger
+DELIMITER $$
+CREATE TRIGGER dhcp6_server_ADEL AFTER DELETE ON dhcp6_server
+    FOR EACH ROW
+    BEGIN
+        CALL createAuditEntryDHCP6('dhcp6_server', OLD.id, "delete");
+    END $$
+DELIMITER ;
+
+# Update the schema version number
+UPDATE schema_version
+SET version = '9', minor = '0';
+
+# This line concludes database upgrade to version 9.0.
+
+EOF
+
+RESULT=$?
+
+exit $?