]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[5351] Checkpoint: added user context in options stored in DBs, todo add tests
authorFrancis Dupont <fdupont@isc.org>
Fri, 1 Dec 2017 08:35:18 +0000 (09:35 +0100)
committerFrancis Dupont <fdupont@isc.org>
Fri, 1 Dec 2017 08:35:18 +0000 (09:35 +0100)
src/lib/dhcpsrv/mysql_host_data_source.cc
src/lib/dhcpsrv/pgsql_exchange.h
src/lib/dhcpsrv/pgsql_host_data_source.cc
src/share/database/scripts/mysql/dhcpdb_create.mysql
src/share/database/scripts/mysql/upgrade_5.0_to_5.1.sh.in
src/share/database/scripts/pgsql/dhcpdb_create.pgsql
src/share/database/scripts/pgsql/upgrade_3.1_to_3.2.sh.in

index 96a7fb12f9f16eb55c45c93fabe04576c2455e10..dbac205fe2e8f3d0a931210660476d8b3ba75e2d 100644 (file)
@@ -34,6 +34,7 @@ using namespace isc;
 using namespace isc::asiolink;
 using namespace isc::dhcp;
 using namespace isc::util;
+using namespace isc::data;
 using namespace std;
 
 namespace {
@@ -63,6 +64,9 @@ const size_t OPTION_FORMATTED_VALUE_MAX_LEN = 8192;
 /// @brief Maximum length of option space name.
 const size_t OPTION_SPACE_MAX_LEN = 128;
 
+/// @brief Maximum length of user context.
+const size_t USER_CONTEXT_MAX_LEN = 8192;
+
 /// @brief Maximum length of the server hostname.
 const size_t SERVER_HOSTNAME_MAX_LEN = 64;
 
@@ -758,7 +762,7 @@ class MySqlHostWithOptionsExchange : public MySqlHostExchange {
 private:
 
     /// @brief Number of columns holding DHCPv4  or DHCPv6 option information.
-    static const size_t OPTION_COLUMNS = 6;
+    static const size_t OPTION_COLUMNS = 7;
 
     /// @brief Receives DHCPv4 or DHCPv6 options information from the
     /// dhcp4_options or dhcp6_options tables respectively.
@@ -787,19 +791,22 @@ private:
                         const size_t start_column)
         : universe_(universe), start_column_(start_column), option_id_(0),
           code_(0), value_length_(0), formatted_value_length_(0),
-          space_length_(0), persistent_(false), option_id_null_(MLM_FALSE),
-          code_null_(MLM_FALSE), value_null_(MLM_FALSE),
-          formatted_value_null_(MLM_FALSE), space_null_(MLM_FALSE),
+          space_length_(0), persistent_(false), user_context_length_(0),
+          option_id_null_(MLM_FALSE), code_null_(MLM_FALSE),
+          value_null_(MLM_FALSE), formatted_value_null_(MLM_FALSE),
+          space_null_(MLM_FALSE), user_context_null_(MLM_FALSE),
           option_id_index_(start_column), code_index_(start_column_ + 1),
           value_index_(start_column_ + 2),
           formatted_value_index_(start_column_ + 3),
           space_index_(start_column_ + 4),
           persistent_index_(start_column_ + 5),
+          user_context_index_(start_column_ + 6),
           most_recent_option_id_(0) {
 
             memset(value_, 0, sizeof(value_));
             memset(formatted_value_, 0, sizeof(formatted_value_));
             memset(space_, 0, sizeof(space_));
+            memset(user_context_, 0, sizeof(user_context_));
         }
 
         /// @brief Returns identifier of the currently processed option.
@@ -858,6 +865,13 @@ private:
                 formatted_value.assign(formatted_value_);
             }
 
+            // Convert user_context to string as well.
+            std::string user_context;
+            if (user_context_null_ == MLM_FALSE) {
+                user_context_[user_context_length_] = '\0';
+                user_context.assign(user_context_);
+            }
+
             // Options are held in a binary or textual format in the database.
             // This is similar to having an option specified in a server
             // configuration file. Such option is converted to appropriate C++
@@ -909,6 +923,22 @@ private:
             }
 
             OptionDescriptor desc(option, persistent_, formatted_value);
+
+            // Set the user context if there is one into the option descriptor.
+            if (!user_context.empty()) {
+                try {
+                    ConstElementPtr ctx = Element::fromJSON(user_context);
+                    if (!ctx || (ctx->getType() != Element::map)) {
+                        isc_throw(BadValue, "user context '" << user_context
+                                  << "' is no a JSON map");
+                    }
+                    desc.setContext(ctx);
+                } catch (const isc::data::JSONError& ex) {
+                    isc_throw(BadValue, "user context '" << user_context
+                              << "' is invalid JSON: " << ex.what());
+                }
+            }
+
             cfg->add(desc, space);
         }
 
@@ -923,6 +953,7 @@ private:
             columns[formatted_value_index_] = "formatted_value";
             columns[space_index_] = "space";
             columns[persistent_index_] = "persistent";
+            columns[user_context_index_] = "user_context";
         }
 
         /// @brief Initialize binding table fields for options.
@@ -975,6 +1006,14 @@ private:
             bind[persistent_index_].buffer_type = MYSQL_TYPE_TINY;
             bind[persistent_index_].buffer = reinterpret_cast<char*>(&persistent_);
             bind[persistent_index_].is_unsigned = MLM_TRUE;
+
+            // user_context : TEXT NULL
+            user_context_length_ = sizeof(user_context_);
+            bind[user_context_index_].buffer_type = MYSQL_TYPE_STRING;
+            bind[user_context_index_].buffer = reinterpret_cast<char*>(user_context_);
+            bind[user_context_index_].buffer_length = user_context_length_;
+            bind[user_context_index_].length = &user_context_length_;
+            bind[user_context_index_].is_null = &user_context_null_;
         }
 
     private:
@@ -1013,6 +1052,12 @@ private:
         /// requested.
         bool persistent_;
 
+        /// @brief Buffer holding textual user context of an option.
+        char user_context_[USER_CONTEXT_MAX_LEN];
+
+        /// @brief User context length.
+        unsigned long user_context_length_;
+
         /// @name Boolean values indicating if values of specific columns in
         /// the database are NULL.
         //@{
@@ -1032,6 +1077,8 @@ private:
         /// @brief Boolean flag indicating if the DHCPv4 option space is NULL.
         my_bool space_null_;
 
+        /// @brief Boolean flag indicating if the DHCPv4 option user context is NULL.
+        my_bool user_context_null_;
         //@}
 
         /// @name Indexes of the specific columns
@@ -1055,6 +1102,9 @@ private:
         size_t persistent_index_;
         //@}
 
+        /// @brief User context;
+        size_t user_context_index_;
+
         /// @brief Option id for last processed row.
         uint32_t most_recent_option_id_;
     };
@@ -1591,17 +1641,19 @@ class MySqlOptionExchange {
 private:
 
     /// @brief Number of columns in the tables holding options.
-    static const size_t OPTION_COLUMNS = 9;
+    static const size_t OPTION_COLUMNS = 10;
 
 public:
 
     /// @brief Constructor.
     MySqlOptionExchange()
-        : type_(0), value_len_(0), formatted_value_len_(0), space_(), space_len_(0),
-          persistent_(false), client_class_(), client_class_len_(0),
+
+        : type_(0), value_len_(0), formatted_value_len_(0), space_(),
+          space_len_(0), persistent_(false), user_context_(),
+          user_context_len_(0), client_class_(), client_class_len_(0),
           subnet_id_(0), host_id_(0), option_() {
 
-        BOOST_STATIC_ASSERT(8 < OPTION_COLUMNS);
+        BOOST_STATIC_ASSERT(9 < OPTION_COLUMNS);
     }
 
     /// @brief Creates binding array to insert option data into database.
@@ -1681,30 +1733,43 @@ public:
             bind_[5].buffer = reinterpret_cast<char*>(&persistent_);
             bind_[5].is_unsigned = MLM_TRUE;
 
+            // user_context: TEST NULL,
+            ConstElementPtr ctx = opt_desc.getContext();
+            if (ctx) {
+                user_context_ = ctx->str();
+                user_context_len_ = user_context_.size();
+                bind_[6].buffer_type = MYSQL_TYPE_STRING;
+                bind_[6].buffer = const_cast<char*>(user_context_.c_str());
+                bind_[6].buffer_length = user_context_len_;
+                bind_[6].length = &user_context_len_;
+            } else {
+                bind_[6].buffer_type = MYSQL_TYPE_NULL;
+            }
+
             // dhcp_client_class: VARCHAR(128) NULL
             /// @todo Assign actual value to client class string.
             client_class_len_ = client_class_.size();
-            bind_[6].buffer_type = MYSQL_TYPE_STRING;
-            bind_[6].buffer = const_cast<char*>(client_class_.c_str());
-            bind_[6].buffer_length = client_class_len_;
-            bind_[6].length = &client_class_len_;
+            bind_[7].buffer_type = MYSQL_TYPE_STRING;
+            bind_[7].buffer = const_cast<char*>(client_class_.c_str());
+            bind_[7].buffer_length = client_class_len_;
+            bind_[7].length = &client_class_len_;
 
             // dhcp4_subnet_id: INT UNSIGNED NULL
             if (subnet_id.isSpecified()) {
                 subnet_id_ = subnet_id;
-                bind_[7].buffer_type = MYSQL_TYPE_LONG;
-                bind_[7].buffer = reinterpret_cast<char*>(subnet_id_);
-                bind_[7].is_unsigned = MLM_TRUE;
+                bind_[8].buffer_type = MYSQL_TYPE_LONG;
+                bind_[8].buffer = reinterpret_cast<char*>(subnet_id_);
+                bind_[8].is_unsigned = MLM_TRUE;
 
             } else {
-                bind_[7].buffer_type = MYSQL_TYPE_NULL;
+                bind_[8].buffer_type = MYSQL_TYPE_NULL;
             }
 
             // host_id: INT UNSIGNED NOT NULL
             host_id_ = host_id;
-            bind_[8].buffer_type = MYSQL_TYPE_LONG;
-            bind_[8].buffer = reinterpret_cast<char*>(&host_id_);
-            bind_[8].is_unsigned = MLM_TRUE;
+            bind_[9].buffer_type = MYSQL_TYPE_LONG;
+            bind_[9].buffer = reinterpret_cast<char*>(&host_id_);
+            bind_[9].is_unsigned = MLM_TRUE;
 
         } catch (const std::exception& ex) {
             isc_throw(DbOperationError,
@@ -1740,6 +1805,12 @@ private:
     /// a client or only when requested.
     bool persistent_;
 
+    /// @brief User context.
+    std::string user_context_;
+
+    /// @brief User context length.
+    unsigned long user_context_len_;
+
     /// @brief Client classes for the option.
     std::string client_class_;
 
@@ -1970,9 +2041,9 @@ TaggedStatementArray tagged_statements = { {
                 "h.hostname, h.dhcp4_client_classes, h.dhcp6_client_classes, "
                 "h.dhcp4_next_server, h.dhcp4_server_hostname, h.dhcp4_boot_file_name, "
                 "o4.option_id, o4.code, o4.value, o4.formatted_value, o4.space, "
-                "o4.persistent, "
+                "o4.persistent, o4.user_context, "
                 "o6.option_id, o6.code, o6.value, o6.formatted_value, o6.space, "
-                "o6.persistent, "
+                "o6.persistent, o6.user_context, "
                 "r.reservation_id, r.address, r.prefix_len, r.type, "
                 "r.dhcp6_iaid "
             "FROM hosts AS h "
@@ -1994,7 +2065,7 @@ TaggedStatementArray tagged_statements = { {
                 "h.dhcp4_client_classes, h.dhcp6_client_classes, "
                 "h.dhcp4_next_server, h.dhcp4_server_hostname, h.dhcp4_boot_file_name, "
                 "o.option_id, o.code, o.value, o.formatted_value, o.space, "
-                "o.persistent "
+                "o.persistent, o.user_context "
             "FROM hosts AS h "
             "LEFT JOIN dhcp4_options AS o "
                 "ON h.host_id = o.host_id "
@@ -2010,7 +2081,7 @@ TaggedStatementArray tagged_statements = { {
                 "h.dhcp4_client_classes, h.dhcp6_client_classes, "
                 "h.dhcp4_next_server, h.dhcp4_server_hostname, h.dhcp4_boot_file_name, "
                 "o.option_id, o.code, o.value, o.formatted_value, o.space, "
-                "o.persistent "
+                "o.persistent, o.user_context "
             "FROM hosts AS h "
             "LEFT JOIN dhcp4_options AS o "
                 "ON h.host_id = o.host_id "
@@ -2028,7 +2099,7 @@ TaggedStatementArray tagged_statements = { {
                 "h.dhcp4_client_classes, h.dhcp6_client_classes, "
                 "h.dhcp4_next_server, h.dhcp4_server_hostname, h.dhcp4_boot_file_name, "
                 "o.option_id, o.code, o.value, o.formatted_value, o.space, "
-                "o.persistent, "
+                "o.persistent, o.user_context, "
                 "r.reservation_id, r.address, r.prefix_len, r.type, "
                 "r.dhcp6_iaid "
             "FROM hosts AS h "
@@ -2050,7 +2121,7 @@ TaggedStatementArray tagged_statements = { {
                 "h.dhcp4_client_classes, h.dhcp6_client_classes, "
                 "h.dhcp4_next_server, h.dhcp4_server_hostname, h.dhcp4_boot_file_name, "
                 "o.option_id, o.code, o.value, o.formatted_value, o.space, "
-                "o.persistent "
+                "o.persistent, o.user_context "
             "FROM hosts AS h "
             "LEFT JOIN dhcp4_options AS o "
                 "ON h.host_id = o.host_id "
@@ -2070,7 +2141,7 @@ TaggedStatementArray tagged_statements = { {
                 "h.dhcp4_client_classes, h.dhcp6_client_classes, "
                 "h.dhcp4_next_server, h.dhcp4_server_hostname, h.dhcp4_boot_file_name, "
                 "o.option_id, o.code, o.value, o.formatted_value, o.space, "
-                "o.persistent, "
+                "o.persistent, o.user_context,"
                 "r.reservation_id, r.address, r.prefix_len, r.type, "
                 "r.dhcp6_iaid "
             "FROM hosts AS h "
@@ -2096,7 +2167,7 @@ TaggedStatementArray tagged_statements = { {
                 "h.dhcp4_client_classes, h.dhcp6_client_classes, "
                 "h.dhcp4_next_server, h.dhcp4_server_hostname, h.dhcp4_boot_file_name, "
                 "o.option_id, o.code, o.value, o.formatted_value, o.space, "
-                "o.persistent, "
+                "o.persistent, o.user_context, "
                 "r.reservation_id, r.address, r.prefix_len, r.type, "
                 "r.dhcp6_iaid "
             "FROM hosts AS h "
@@ -2129,15 +2200,15 @@ TaggedStatementArray tagged_statements = { {
     // Using fixed scope_id = 3, which associates an option with host.
     {MySqlHostDataSourceImpl::INSERT_V4_OPTION,
          "INSERT INTO dhcp4_options(option_id, code, value, formatted_value, space, "
-            "persistent, dhcp_client_class, dhcp4_subnet_id, host_id, scope_id) "
-         " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 3)"},
+            "persistent, user_context, dhcp_client_class, dhcp4_subnet_id, host_id, scope_id) "
+         " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 3)"},
 
     // Inserts a single DHCPv6 option into 'dhcp6_options' table.
     // Using fixed scope_id = 3, which associates an option with host.
     {MySqlHostDataSourceImpl::INSERT_V6_OPTION,
          "INSERT INTO dhcp6_options(option_id, code, value, formatted_value, space, "
-            "persistent, dhcp_client_class, dhcp6_subnet_id, host_id, scope_id) "
-         " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 3)"},
+            "persistent, user_context, dhcp_client_class, dhcp6_subnet_id, host_id, scope_id) "
+         " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 3)"},
 
     {MySqlHostDataSourceImpl::DEL_HOST_ADDR4,
      "DELETE FROM hosts WHERE dhcp4_subnet_id = ? AND ipv4_address = ?"},
index ea21627913921e90d00128e7d0814246f556de4c..381b4b1891c9526f2789deee6d9b49f0f4e65221 100644 (file)
@@ -160,7 +160,7 @@ struct PsqlBindArray {
 
     /// @brief Binds a the given string to the bind array.
     ///
-    /// Prior to added the The given string the vector of exchange values,
+    /// Prior to add the given string the vector of exchange values,
     /// it duplicated as a ConstStringPtr and saved internally.  This guarantees
     /// the string remains in scope until the PsqlBindArray is destroyed,
     /// without the caller maintaining the string values.
index ead3b672cef53b1be35e1129308672ccd035c10a..580f03dd2a983d112f206dd79ce45282f9cdb006 100644 (file)
@@ -31,6 +31,7 @@ using namespace isc;
 using namespace isc::asiolink;
 using namespace isc::dhcp;
 using namespace isc::util;
+using namespace isc::data;
 using namespace std;
 
 namespace {
@@ -399,7 +400,7 @@ class PgSqlHostWithOptionsExchange : public PgSqlHostExchange {
 private:
 
     /// @brief Number of columns holding DHCPv4  or DHCPv6 option information.
-    static const size_t OPTION_COLUMNS = 6;
+    static const size_t OPTION_COLUMNS = 7;
 
     /// @brief Receives DHCPv4 or DHCPv6 options information from the
     /// dhcp4_options or dhcp6_options tables respectively.
@@ -432,6 +433,7 @@ private:
           formatted_value_index_(start_column_ + 3),
           space_index_(start_column_ + 4),
           persistent_index_(start_column_ + 5),
+          user_context_index_(start_column_ + 6),
           most_recent_option_id_(0) {
         }
 
@@ -533,6 +535,13 @@ private:
             PgSqlExchange::getColumnValue(r, row, persistent_index_,
                                           persistent);
 
+            // user_context: TEXT
+            std::string user_context;
+            if (!isColumnNull(r, row, user_context_index_)) {
+                PgSqlExchange::getColumnValue(r, row, user_context_index_,
+                                              user_context);
+            }
+
             // Options are held in a binary or textual format in the database.
             // This is similar to having an option specified in a server
             // configuration file. Such option is converted to appropriate C++
@@ -588,6 +597,22 @@ private:
             }
 
             OptionDescriptor desc(option, persistent, formatted_value);
+
+            // Set the user context if there is one into the option descriptor.
+            if (!user_context.empty()) {
+                try {
+                    ConstElementPtr ctx = Element::fromJSON(user_context);
+                    if (!ctx || (ctx->getType() != Element::map)) {
+                        isc_throw(BadValue, "user context '" << user_context
+                                  << "' is no a JSON map");
+                    }
+                    desc.setContext(ctx);
+                } catch (const isc::data::JSONError& ex) {
+                    isc_throw(BadValue, "user context '" << user_context
+                              << "' is invalid JSON: " << ex.what());
+                }
+            }
+
             cfg->add(desc, space);
         }
 
@@ -602,6 +627,7 @@ private:
             columns[formatted_value_index_] = "formatted_value";
             columns[space_index_] = "space";
             columns[persistent_index_] = "persistent";
+            columns[user_context_index_] = "user_context";
         }
 
     private:
@@ -634,6 +660,9 @@ private:
         size_t persistent_index_;
         //@}
 
+        /// @brief User context
+        size_t user_context_index_;
+
         /// @brief Option id for last processed row.
         uint64_t most_recent_option_id_;
     };
@@ -1049,13 +1078,14 @@ private:
     static const int FORMATTED_VALUE_COL = 3;
     static const int SPACE_COL = 4;
     static const int PERSISTENT_COL = 5;
-    static const int DHCP_CLIENT_CLASS_COL = 6;
-    static const int DHCP_SUBNET_ID_COL = 7;
-    static const int HOST_ID_COL = 8;
-    static const int SCOPE_ID_COL = 9;
+    static const int USER_CONTEXT_COL = 6;
+    static const int DHCP_CLIENT_CLASS_COL = 7;
+    static const int DHCP_SUBNET_ID_COL = 8;
+    static const int HOST_ID_COL = 9;
+    static const int SCOPE_ID_COL = 10;
 
     /// @brief Number of columns in the tables holding options.
-    static const size_t OPTION_COLUMNS = 10;
+    static const size_t OPTION_COLUMNS = 11;
 
 public:
 
@@ -1069,12 +1099,13 @@ public:
         columns_[FORMATTED_VALUE_COL] = "formatted_value";
         columns_[SPACE_COL] = "space";
         columns_[PERSISTENT_COL] = "persistent";
+        columns_[USER_CONTEXT_COL] = "user_context";
         columns_[DHCP_CLIENT_CLASS_COL] = "dhcp_client_class";
         columns_[DHCP_SUBNET_ID_COL] = "dhcp_subnet_id";
         columns_[HOST_ID_COL] = "host_id";
         columns_[SCOPE_ID_COL] = "scope_id";
 
-        BOOST_STATIC_ASSERT(9 < OPTION_COLUMNS);
+        BOOST_STATIC_ASSERT(10 < OPTION_COLUMNS);
     }
 
     /// @brief Creates binding array to insert option data into database.
@@ -1138,6 +1169,15 @@ public:
             // persistent: BOOLEAN DEFAULT false
             bind_array->add(opt_desc.persistent_);
 
+            // user_context: TEXT NULL,
+            ConstElementPtr ctx = opt_desc.getContext();
+            if (ctx) {
+                std::string user_context_ = ctx->str();
+                bind_array->addTempString(user_context_);
+            } else {
+                bind_array->addNull();
+            }
+
             // host_id: INT NULL
             if (!host_id) {
                 isc_throw(BadValue, "host_id cannot be null");
@@ -1389,9 +1429,9 @@ TaggedStatementArray tagged_statements = { {
      "  h.hostname, h.dhcp4_client_classes, h.dhcp6_client_classes, "
      "  h.dhcp4_next_server, h.dhcp4_server_hostname, h.dhcp4_boot_file_name, "
      "  o4.option_id, o4.code, o4.value, o4.formatted_value, o4.space, "
-     "  o4.persistent, "
+     "  o4.persistent, o4.user_context, "
      "  o6.option_id, o6.code, o6.value, o6.formatted_value, o6.space, "
-     "  o6.persistent, "
+     "  o6.persistent, o6.user_context, "
      "  r.reservation_id, r.address, r.prefix_len, r.type, r.dhcp6_iaid "
      "FROM hosts AS h "
      "LEFT JOIN dhcp4_options AS o4 ON h.host_id = o4.host_id "
@@ -1411,7 +1451,8 @@ TaggedStatementArray tagged_statements = { {
      "  h.dhcp4_subnet_id, h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
      "  h.dhcp4_client_classes, h.dhcp6_client_classes, "
      "  h.dhcp4_next_server, h.dhcp4_server_hostname, h.dhcp4_boot_file_name, "
-     "  o.option_id, o.code, o.value, o.formatted_value, o.space, o.persistent "
+     "  o.option_id, o.code, o.value, o.formatted_value, o.space, "
+     "  o.persistent, o.user_context "
      "FROM hosts AS h "
      "LEFT JOIN dhcp4_options AS o ON h.host_id = o.host_id "
      "WHERE ipv4_address = $1 "
@@ -1429,7 +1470,8 @@ TaggedStatementArray tagged_statements = { {
      "  h.dhcp4_subnet_id, h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
      "  h.dhcp4_client_classes, h.dhcp6_client_classes, "
      "  h.dhcp4_next_server, h.dhcp4_server_hostname, h.dhcp4_boot_file_name, "
-     "  o.option_id, o.code, o.value, o.formatted_value, o.space, o.persistent "
+     "  o.option_id, o.code, o.value, o.formatted_value, o.space, "
+     "  o.persistent, o.user_context "
      "FROM hosts AS h "
      "LEFT JOIN dhcp4_options AS o ON h.host_id = o.host_id "
      "WHERE h.dhcp4_subnet_id = $1 AND h.dhcp_identifier_type = $2 "
@@ -1450,7 +1492,7 @@ TaggedStatementArray tagged_statements = { {
      "  h.dhcp4_client_classes, h.dhcp6_client_classes, "
      "  h.dhcp4_next_server, h.dhcp4_server_hostname, h.dhcp4_boot_file_name, "
      "  o.option_id, o.code, o.value, o.formatted_value, o.space, "
-     "  o.persistent, "
+     "  o.persistent, o.user_context, "
      "  r.reservation_id, r.address, r.prefix_len, r.type, r.dhcp6_iaid "
      "FROM hosts AS h "
      "LEFT JOIN dhcp6_options AS o ON h.host_id = o.host_id "
@@ -1472,7 +1514,8 @@ TaggedStatementArray tagged_statements = { {
      "  h.dhcp4_subnet_id, h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
      "  h.dhcp4_client_classes, h.dhcp6_client_classes, "
      "  h.dhcp4_next_server, h.dhcp4_server_hostname, h.dhcp4_boot_file_name, "
-     "  o.option_id, o.code, o.value, o.formatted_value, o.space, o.persistent "
+     "  o.option_id, o.code, o.value, o.formatted_value, o.space, "
+     "  o.persistent, o.user_context "
      "FROM hosts AS h "
      "LEFT JOIN dhcp4_options AS o ON h.host_id = o.host_id "
      "WHERE h.dhcp4_subnet_id = $1 AND h.ipv4_address = $2 "
@@ -1495,7 +1538,7 @@ TaggedStatementArray tagged_statements = { {
      "  h.dhcp4_client_classes, h.dhcp6_client_classes, "
      "  h.dhcp4_next_server, h.dhcp4_server_hostname, h.dhcp4_boot_file_name, "
      "  o.option_id, o.code, o.value, o.formatted_value, o.space, "
-     "  o.persistent, "
+     "  o.persistent, o.user_context, "
      "  r.reservation_id, r.address, r.prefix_len, r.type, "
      "  r.dhcp6_iaid "
      "FROM hosts AS h "
@@ -1523,7 +1566,7 @@ TaggedStatementArray tagged_statements = { {
      "  h.dhcp4_client_classes, h.dhcp6_client_classes, "
      "  h.dhcp4_next_server, h.dhcp4_server_hostname, h.dhcp4_boot_file_name, "
      "  o.option_id, o.code, o.value, o.formatted_value, o.space, "
-     "  o.persistent, "
+     "  o.persistent, o.user_context, "
      "  r.reservation_id, r.address, r.prefix_len, r.type, "
      "  r.dhcp6_iaid "
      "FROM hosts AS h "
@@ -1568,25 +1611,25 @@ TaggedStatementArray tagged_statements = { {
     // PgSqlHostDataSourceImpl::INSERT_V4_HOST_OPTION
     // Inserts a single DHCPv4 option into 'dhcp4_options' table.
     // Using fixed scope_id = 3, which associates an option with host.
-    {6,
+    {7,
      { OID_INT2, OID_BYTEA, OID_TEXT,
-       OID_VARCHAR, OID_BOOL, OID_INT8},
+       OID_VARCHAR, OID_BOOL, OID_TEXT, OID_INT8},
      "insert_v4_host_option",
      "INSERT INTO dhcp4_options(code, value, formatted_value, space, "
-     "  persistent, host_id, scope_id) "
-     "VALUES ($1, $2, $3, $4, $5, $6, 3)"
+     "  persistent, user_context, host_id, scope_id) "
+     "VALUES ($1, $2, $3, $4, $5, $6, $7, 3)"
     },
 
     // PgSqlHostDataSourceImpl::INSERT_V6_HOST_OPTION
     // Inserts a single DHCPv6 option into 'dhcp6_options' table.
     // Using fixed scope_id = 3, which associates an option with host.
-    {6,
+    {7,
      { OID_INT2, OID_BYTEA, OID_TEXT,
-       OID_VARCHAR, OID_BOOL, OID_INT8},
+       OID_VARCHAR, OID_BOOL, OID_TEXT, OID_INT8},
      "insert_v6_host_option",
      "INSERT INTO dhcp6_options(code, value, formatted_value, space, "
-     "  persistent, host_id, scope_id) "
-     "VALUES ($1, $2, $3, $4, $5, $6, 3)"
+     "  persistent, user_context, host_id, scope_id) "
+     "VALUES ($1, $2, $3, $4, $5, $6, $7, 3)"
     },
 
     // PgSqlHostDataSourceImpl::DEL_HOST_ADDR4
index bb82fc33ddbc428cccc1b5458ffe140903e8a262..3259648ea7dcc7f290f27d068577391489e1a03f 100644 (file)
@@ -498,6 +498,9 @@ END
 $$
 DELIMITER ;
 
+# Add user contexts into tables holding DHCP options
+ALTER TABLE dhcp4_options ADD COLUMN user_context TEXT NULL;
+ALTER TABLE dhcp6_options ADD COLUMN user_context TEXT NULL;
 
 # Update the schema version number
 UPDATE schema_version
index 14d0ef013910731994cb03cd477c089841e09566..54f81092505a8039521843583dd9727f17598e36 100644 (file)
@@ -35,6 +35,10 @@ END
 $$
 DELIMITER ;
 
+# Add user contexts into tables holding DHCP options
+ALTER TABLE dhcp4_options ADD COLUMN user_context TEXT NULL;
+ALTER TABLE dhcp6_options ADD COLUMN user_context TEXT NULL;
+
 # Update the schema version number
 UPDATE schema_version
 SET version = '5', minor = '1';
index 3597b7334051f1859709ebe8ab3344853df38054..51a50616f9087520d57bea18da79e5b524c83ee8 100644 (file)
@@ -524,6 +524,10 @@ CREATE UNIQUE INDEX key_dhcp6_identifier_subnet_id ON hosts
         (dhcp_identifier ASC, dhcp_identifier_type ASC, dhcp6_subnet_id ASC)
     WHERE (dhcp6_subnet_id IS NOT NULL AND dhcp6_subnet_id <> 0);
 
+-- Add a column holding DHCP options for user context.
+ALTER TABLE dhcp4_options ADD COLUMN user_context TEXT;
+ALTER TABLE dhcp6_options ADD COLUMN user_context TEXT;
+
 -- Set 3.2 schema version.
 UPDATE schema_version
     SET version = '3', minor = '2';
index 3e4c44c66abbe6846d0bc213adf4f0d1360f78df..78e212ce5c195de4eb2b64d8491469794a911515 100644 (file)
@@ -48,6 +48,10 @@ CREATE UNIQUE INDEX hosts_dhcp6_identifier_subnet_id ON hosts
         (dhcp_identifier ASC, dhcp_identifier_type ASC, dhcp6_subnet_id ASC)
     WHERE (dhcp6_subnet_id IS NOT NULL AND dhcp6_subnet_id <> 0);
 
+-- Add a column holding DHCP options for user context.
+ALTER TABLE dhcp4_options ADD COLUMN user_context TEXT;
+ALTER TABLE dhcp6_options ADD COLUMN user_context TEXT;
+
 -- Set 3.2 schema version.
 UPDATE schema_version
     SET version = '3', minor = '2';