From 6351f21f60ca3d3e343f223e95064d3f533d9043 Mon Sep 17 00:00:00 2001 From: Marcin Siodelski Date: Wed, 21 Jul 2021 13:24:02 +0200 Subject: [PATCH] [#1976] Server tag is now 64 characters long --- src/bin/admin/tests/mysql_tests.sh.in | 43 +++++++++++++ src/lib/config_backend/constants.h | 2 +- .../scripts/mysql/dhcpdb_create.mysql | 4 +- .../scripts/mysql/upgrade_6.0_to_7.0.sh.in | 4 +- .../scripts/mysql/upgrade_9.6_to_10.0.sh.in | 63 +++++++++++++++++++ 5 files changed, 111 insertions(+), 5 deletions(-) diff --git a/src/bin/admin/tests/mysql_tests.sh.in b/src/bin/admin/tests/mysql_tests.sh.in index 7f33975ff9..d3830b6859 100644 --- a/src/bin/admin/tests/mysql_tests.sh.in +++ b/src/bin/admin/tests/mysql_tests.sh.in @@ -1680,6 +1680,48 @@ mysql_client_class_test() { test_finish 0 } +# Verifies that the migration 9.6 to 10.0 modifies the length of +# the tag column in the dhcp4_server and dhcp6_server tables. +mysql_shrink_server_tag_test() { + + test_start "mysql_shrink_server_tag_test" + + mysql_wipe + + mysql -u"${db_user}" -p"${db_password}" "${db_name}" < "@abs_top_srcdir@/src/bin/admin/tests/dhcpdb_create_1.0.mysql" + # Now upgrade to schema 9.6. + mysql_upgrade_schema_to_version 9.6 + + # Unfortunatelly, this schema version already contains 64 character + # long server tags. Let's extend it back, but not to 256 characters + # because it is proven to cause errors in some configurations. + sql=\ +"ALTER TABLE dhcp4_server MODIFY COLUMN tag VARCHAR(128) NOT NULL;" + run_statement "extend server DHCPv4 server tag column", "$sql" + + sql=\ +"ALTER TABLE dhcp6_server MODIFY COLUMN tag VARCHAR(128) NOT NULL;" + run_statement "extend server DHCPv6 server tag column", "$sql" + + mysql_upgrade_schema_to_version 10.0 + + # Ensure that the migration corrected the lengths. + sql=\ +"SELECT CHARACTER_MAXIMUM_LENGTH \ + FROM INFORMATION_SCHEMA.COLUMNS \ + WHERE TABLE_SCHEMA='${db_name}' AND TABLE_NAME='dhcp4_server' AND COLUMN_NAME='tag';" + run_statement "get new tag column length" "$sql" 64 + + sql=\ +"SELECT CHARACTER_MAXIMUM_LENGTH \ + FROM INFORMATION_SCHEMA.COLUMNS \ + WHERE TABLE_SCHEMA='${db_name}' AND TABLE_NAME='dhcp6_server' AND COLUMN_NAME='tag';" + run_statement "get new tag column length" "$sql" 64 + + mysql_wipe + + test_finish 0 +} # Run tests. mysql_db_init_test @@ -1696,3 +1738,4 @@ mysql_unused_subnet_id_test mysql_reservation_mode_upgrade_test mysql_client_class_test dhcp4 mysql_client_class_test dhcp6 +mysql_shrink_server_tag_test diff --git a/src/lib/config_backend/constants.h b/src/lib/config_backend/constants.h index f6bba65dd0..ba20b78604 100644 --- a/src/lib/config_backend/constants.h +++ b/src/lib/config_backend/constants.h @@ -74,7 +74,7 @@ constexpr unsigned long AUDIT_ENTRY_OBJECT_TYPE_BUF_LENGTH = 256; constexpr unsigned long AUDIT_ENTRY_LOG_MESSAGE_BUF_LENGTH = 65536; -constexpr unsigned long SERVER_TAG_BUF_LENGTH = 256; +constexpr unsigned long SERVER_TAG_BUF_LENGTH = 64; constexpr unsigned long SERVER_DESCRIPTION_BUF_LENGTH = 65536; diff --git a/src/share/database/scripts/mysql/dhcpdb_create.mysql b/src/share/database/scripts/mysql/dhcpdb_create.mysql index 8930ea6eb6..db573cd16a 100644 --- a/src/share/database/scripts/mysql/dhcpdb_create.mysql +++ b/src/share/database/scripts/mysql/dhcpdb_create.mysql @@ -804,7 +804,7 @@ INSERT INTO modification(id, modification_type) -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS dhcp4_server ( id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, - tag VARCHAR(256) NOT NULL, + tag VARCHAR(64) NOT NULL, description TEXT, modification_ts TIMESTAMP NOT NULL, PRIMARY KEY (id), @@ -1062,7 +1062,7 @@ DELIMITER ; -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS dhcp6_server ( id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, - tag VARCHAR(256) NOT NULL, + tag VARCHAR(64) NOT NULL, description TEXT, modification_ts TIMESTAMP NOT NULL, PRIMARY KEY (id), diff --git a/src/share/database/scripts/mysql/upgrade_6.0_to_7.0.sh.in b/src/share/database/scripts/mysql/upgrade_6.0_to_7.0.sh.in index 886a5fab2e..5d83da5866 100644 --- a/src/share/database/scripts/mysql/upgrade_6.0_to_7.0.sh.in +++ b/src/share/database/scripts/mysql/upgrade_6.0_to_7.0.sh.in @@ -162,7 +162,7 @@ INSERT INTO modification(id, modification_type) # CREATE TABLE IF NOT EXISTS dhcp4_server ( id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, - tag VARCHAR(256) NOT NULL, + tag VARCHAR(64) NOT NULL, description TEXT, modification_ts TIMESTAMP NOT NULL, PRIMARY KEY (id), @@ -405,7 +405,7 @@ DELIMITER ; # CREATE TABLE IF NOT EXISTS dhcp6_server ( id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, - tag VARCHAR(256) NOT NULL, + tag VARCHAR(64) NOT NULL, description TEXT, modification_ts TIMESTAMP NOT NULL, PRIMARY KEY (id), diff --git a/src/share/database/scripts/mysql/upgrade_9.6_to_10.0.sh.in b/src/share/database/scripts/mysql/upgrade_9.6_to_10.0.sh.in index b54547d912..081b6bf112 100644 --- a/src/share/database/scripts/mysql/upgrade_9.6_to_10.0.sh.in +++ b/src/share/database/scripts/mysql/upgrade_9.6_to_10.0.sh.in @@ -33,6 +33,69 @@ if test "${version}" != "9.6"; then exit 0 fi +# Get the schema name from database argument. We need this to +# query information_schema for the right database. +for arg in "${@}" +do + if ! printf '%s' "${arg}" | grep -Eq '^\-\-' + then + schema="$arg" + break + fi +done + +# Make sure we have the schema. +if [ -z "$schema" ] +then + printf "Could not find database schema name in cmd line args: %s\n" "${*}" + exit 255 +fi + +shrink_tag_column() { + local schema="${1-}"; shift + local table="${1-}"; shift + + # Check if the table already has a correct server tag length. + sql="SELECT CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='${schema}' AND TABLE_NAME='${table}' AND COLUMN_NAME='tag'" + if ! taglen=$(mysql -N -B "${@}" -e "${sql}") + then + printf 'shrink_tag_column: schema query failed [%s]\n' "${sql}" + exit 255 + fi + + # We aim for the length of 64 characters. + if [ "$taglen" -ne 64 ] + then + # Check if any of the tags are longer than 64 characters. + sql="SELECT COUNT(*) FROM $table WHERE CHAR_LENGTH(tag) > 64 LIMIT 1" + if ! longtag=$(mysql -N -B "${@}" -e "${sql}") + then + printf 'shrink_tag_column: select query failed [%s]\n' "${sql}" + exit 255 + fi + # Report an error if there are any server tags exceeding 64 characters. + # A user should fix the tags and rerun this migration. + if [ "$longtag" -eq 1 ] + then + printf 'shrink_tag_column: failed to resize server tag column for table %s.\n' "${table}" + printf 'Ensure that no server tags are longer than 64 characters and rerun this migration.\n' + printf 'The remote-server4-set and remote-server6-set commands from the cb_cmds hooks\n' + printf 'library can be used to modify the tags.\n' + exit 255 + fi + # If there are no long server tags we can safely alter the column. + sql="ALTER TABLE $table MODIFY COLUMN tag VARCHAR(64) NOT NULL" + if ! mysql -N -B "${@}" -e "${sql}" + then + printf 'shrink_tag_column: alter quary failed [%s]\n' "${sql}" + exit 255 + fi + fi +} + +shrink_tag_column "${schema}" dhcp4_server "${@}" +shrink_tag_column "${schema}" dhcp6_server "${@}" + mysql "$@" <