%PDF- %PDF-
Direktori : /backups/router/usr/local/share/kea/scripts/pgsql/ |
Current File : //backups/router/usr/local/share/kea/scripts/pgsql/upgrade_007_to_008.sh |
#!/bin/sh # Copyright (C) 2021-2024 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # Exit with error if commands exit with non-zero and if undefined variables are # used. set -eu # shellcheck disable=SC2034 # SC2034: ... appears unused. Verify use (or export if used externally). prefix="/usr/local" # Include utilities based on location of this script. Check for sources first, # so that the unexpected situations with weird paths fall on the default # case of installed. script_path=$(cd "$(dirname "${0}")" && pwd) if test "${script_path}" = "/usr/obj/usr/ports/net/kea/work/kea-2.6.1/src/share/database/scripts/pgsql"; then # shellcheck source=./src/bin/admin/admin-utils.sh.in . "/usr/obj/usr/ports/net/kea/work/kea-2.6.1/src/bin/admin/admin-utils.sh" else # shellcheck source=./src/bin/admin/admin-utils.sh.in . "${prefix}/share/kea/scripts/admin-utils.sh" fi VERSION=$(pgsql_version "$@") if [ "$VERSION" != "7.0" ]; then printf 'This script upgrades 7.0 to 8.0. ' printf 'Reported version is %s. Skipping upgrade.\n' "${VERSION}" exit 0 fi psql "$@" >/dev/null <<EOF START TRANSACTION; -- This line starts the schema upgrade to version 8.0. -- Adds a few missing elements for CB and functions for kea-admin's lease-dump -- and lease-upload commands. -- ----------------------------------------------------------------------- -- Extend the table holding DHCPv4 option definitions with a nullable -- column matching option defintions with client classes. -- ----------------------------------------------------------------------- ALTER TABLE dhcp4_option_def ADD COLUMN class_id BIGINT NULL DEFAULT NULL; ALTER TABLE dhcp4_option_def ADD CONSTRAINT fk_dhcp4_option_def_client_class_id FOREIGN KEY (class_id) REFERENCES dhcp4_client_class (id) ON DELETE CASCADE ON UPDATE CASCADE; -- ----------------------------------------------------------------------- -- Extend the table holding DHCPv6 option definitions with a nullable -- column matching option defintions with client classes. -- ----------------------------------------------------------------------- ALTER TABLE dhcp6_option_def ADD COLUMN class_id BIGINT NULL DEFAULT NULL; ALTER TABLE dhcp6_option_def ADD CONSTRAINT fk_dhcp6_option_def_client_class_id FOREIGN KEY (class_id) REFERENCES dhcp6_client_class (id) ON DELETE CASCADE ON UPDATE CASCADE; -- ----------------------------------------------------------------------- -- Add missing preferred_lifetime columns to dhcp6_client_class table. -- ----------------------------------------------------------------------- ALTER TABLE dhcp6_client_class ADD COLUMN preferred_lifetime BIGINT DEFAULT NULL, ADD COLUMN min_preferred_lifetime BIGINT DEFAULT NULL, ADD COLUMN max_preferred_lifetime BIGINT DEFAULT NULL; -- ----------------------------------------------------------------------- -- Add option scopes -- ----------------------------------------------------------------------- -- Add scope for shared network specific options. INSERT INTO dhcp_option_scope (scope_id, scope_name) VALUES(4, 'shared-network'); -- Add scope for pool specific options. INSERT INTO dhcp_option_scope (scope_id, scope_name) VALUES(5, 'pool'); -- Add scope for PD pool specific options. INSERT INTO dhcp_option_scope (scope_id, scope_name) VALUES(6, 'pd-pool'); -- Drop the existing function, createOptionAuditDHCP6 so we can replace it -- with one that has slightly different arguments. DROP FUNCTION IF EXISTS createOptionAuditDHCP6(modification_type VARCHAR(32), scope_id SMALLINT, option_id INT, subnet_id BIGINT, host_id INT, network_name VARCHAR(128), pool_id BIGINT, pd_pool_id BIGINT, modification_ts TIMESTAMP WITH TIME ZONE); -- ----------------------------------------------------- -- -- New version of the createOptionAuditDHCP6 stored -- procedure which updates modification timestamp of -- a parent object when an option is modified. -- -- The following parameters are passed to the procedure: -- - modification_type: "create", "update" or "delete" -- - scope_id: identifier of the option scope, e.g. -- global, subnet specific etc. See dhcp_option_scope -- for specific values. -- - option_id: identifier of the option. -- - subnet_id: identifier of the subnet if the option -- belongs to the subnet. -- - host_id: identifier of the host if the option -- - belongs to the host. -- - network_name: shared network name if the option -- belongs to the shared network. -- - pool_id: identifier of the pool if the option -- belongs to the pool. -- - pd_pool_id: identifier of the pool if the option -- belongs to the pd pool. -- - modification_ts: modification timestamp of the -- option. -- Some arguments are prefixed with "p_" to avoid ambiguity -- with column names in SQL statements. PostgreSQL does not -- allow table aliases to be used with column names in update -- set expressions. -- ----------------------------------------------------- CREATE OR REPLACE FUNCTION createOptionAuditDHCP6(modification_type VARCHAR(32), scope_id SMALLINT, option_id INT, p_subnet_id BIGINT, host_id INT, network_name VARCHAR(128), pool_id BIGINT, pd_pool_id BIGINT, p_modification_ts TIMESTAMP WITH TIME ZONE) RETURNS VOID LANGUAGE plpgsql AS \$\$ DECLARE -- These variables will hold shared network id and subnet id that -- we will select. snid VARCHAR(128); sid BIGINT; cascade_transaction BOOLEAN := false; BEGIN -- Cascade transaction flag is set to true to prevent creation of -- the audit entries for the options when the options are -- created as part of the parent object creation or update. -- For example: when the option is added as part of the subnet -- addition, the cascade transaction flag is equal to true. If -- the option is added into the existing subnet the cascade -- transaction is equal to false. Note that depending on the option -- scope the audit entry will contain the object_type value -- of the parent object to cause the server to replace the -- entire subnet. The only case when the object_type will be -- set to 'dhcp6_options' is when a global option is added. -- Global options do not have the owner. cascade_transaction := get_session_boolean('kea.cascade_transaction'); IF cascade_transaction = false THEN -- todo: host manager hasn't been updated to use audit -- mechanisms so ignore host specific options for now. IF scope_id = 0 THEN -- If a global option is added or modified, create audit -- entry for the 'dhcp6_options' table. PERFORM createAuditEntryDHCP6('dhcp6_options', option_id, modification_type); ELSEIF scope_id = 1 THEN -- If subnet specific option is added or modified, update -- the modification timestamp of this subnet to allow the -- servers to refresh the subnet information. This will -- also result in creating an audit entry for this subnet. UPDATE dhcp6_subnet SET modification_ts = p_modification_ts WHERE subnet_id = p_subnet_id; ELSEIF scope_id = 4 THEN -- If shared network specific option is added or modified, -- update the modification timestamp of this shared network -- to allow the servers to refresh the shared network -- information. This will also result in creating an -- audit entry for this shared network. SELECT id INTO snid FROM dhcp6_shared_network WHERE name = network_name LIMIT 1; UPDATE dhcp6_shared_network SET modification_ts = p_modification_ts WHERE id = snid; ELSEIF scope_id = 5 THEN -- If pool specific option is added or modified, update -- the modification timestamp of the owning subnet. SELECT dhcp6_pool.subnet_id INTO sid FROM dhcp6_pool WHERE id = pool_id; UPDATE dhcp6_subnet SET modification_ts = p_modification_ts WHERE subnet_id = sid; ELSEIF scope_id = 6 THEN -- If pd pool specific option is added or modified, create -- audit entry for the subnet which this pool belongs to. SELECT dhcp6_pd_pool.subnet_id INTO sid FROM dhcp6_pd_pool WHERE id = pool_id; UPDATE dhcp6_subnet SET modification_ts = p_modification_ts WHERE subnet_id = sid; END IF; END IF; RETURN; END;\$\$; -- Fix mangled constraints on dhcp4_subnet_server table. ALTER TABLE dhcp4_subnet_server DROP CONSTRAINT fk_dhcp6_subnet_server_server_id, ADD CONSTRAINT fk_dhcp4_subnet_server_server_id FOREIGN KEY (server_id) REFERENCES dhcp4_server (id) ON DELETE NO ACTION ON UPDATE NO ACTION, DROP CONSTRAINT fk_dhcp6_subnet_server_subnet_id, ADD CONSTRAINT fk_dhcp4_subnet_server_subnet_id FOREIGN KEY (subnet_id) REFERENCES dhcp4_subnet (subnet_id) ON DELETE CASCADE ON UPDATE NO ACTION; -- Add missing foreign key indexes. PostgreSQL does not automatically create indexes for -- foreign key constraints. These have been added using the basic guideline: -- -- If the constraint does not reference a static table (e.g. parameter_data_type), -- and the referencing column is not the primary key or the first -- column in the primary key, and does not already have an index, then an index -- should be added to the table for the referencing column. -- -- dhcp6_global_parameter_server CREATE INDEX fk_dhcp6_global_parameter_server_server_id ON dhcp6_global_parameter_server (server_id); -- dhcp6_options -- Missing foreign key constraint and indexes ALTER TABLE dhcp6_options ADD CONSTRAINT fk_dhcp6_options_subnet FOREIGN KEY (dhcp6_subnet_id) REFERENCES dhcp6_subnet(subnet_id) ON DELETE CASCADE ON UPDATE CASCADE; CREATE INDEX fk_dhcp6_options_subnet ON dhcp6_options (dhcp6_subnet_id); CREATE INDEX fk_dhcp6_options_pd_pool ON dhcp6_options (pd_pool_id); CREATE INDEX fk_dhcp6_options_pool ON dhcp6_options (pool_id); CREATE INDEX fk_dhcp6_options_shared_network ON dhcp6_options (shared_network_name); -- dhcp6_option_def_server -- Missing foreign key constraints and index ALTER TABLE dhcp6_option_def_server ADD CONSTRAINT fk_dhcp6_option_def_server_option_def_id FOREIGN KEY (option_def_id) REFERENCES dhcp6_option_def (id) ON DELETE CASCADE ON UPDATE NO ACTION, ADD CONSTRAINT fk_dhcp6_option_def_server_server_id FOREIGN KEY (server_id) REFERENCES dhcp6_server (id) ON DELETE NO ACTION ON UPDATE NO ACTION; CREATE INDEX fk_dhcp6_option_def_server_server_id ON dhcp6_option_def_server (server_id); -- dhcp6_option_def CREATE INDEX fk_dhcp6_option_def_client_class_id ON dhcp6_option_def (class_id); -- dhcp4_global_parameter_server CREATE INDEX fk_dhcp4_global_parameter_server_server_id ON dhcp4_global_parameter_server (server_id); -- dhcp4_options -- Missing foreign key constraint and indexes ALTER TABLE dhcp4_options ADD CONSTRAINT fk_dhcp4_options_subnet FOREIGN KEY (dhcp4_subnet_id) REFERENCES dhcp4_subnet(subnet_id) ON DELETE CASCADE ON UPDATE CASCADE; CREATE INDEX fk_dhcp4_options_subnet ON dhcp4_options (dhcp4_subnet_id); CREATE INDEX fk_dhcp4_options_pool ON dhcp4_options (pool_id); CREATE INDEX fk_dhcp4_options_shared_network ON dhcp4_options (shared_network_name); -- dhcp4_option_def_server -- Missing foreign key constraints and index ALTER TABLE dhcp4_option_def_server ADD CONSTRAINT fk_dhcp4_option_def_server_option_def_id FOREIGN KEY (option_def_id) REFERENCES dhcp4_option_def (id) ON DELETE CASCADE ON UPDATE NO ACTION, ADD CONSTRAINT fk_dhcp4_option_def_server_server_id FOREIGN KEY (server_id) REFERENCES dhcp4_server (id) ON DELETE NO ACTION ON UPDATE NO ACTION; CREATE INDEX fk_dhcp4_option_def_server_server_id ON dhcp4_option_def_server (server_id); -- dhcp4_option_def CREATE INDEX fk_dhcp4_option_def_client_class_id ON dhcp4_option_def (class_id); -- Create a function that separates groups of two hexadecimals -- with colons. CREATE OR REPLACE FUNCTION colonSeparatedHex(hex TEXT) RETURNS TEXT AS \$\$ DECLARE i INT := 3; length INT := LENGTH(hex); output TEXT; BEGIN -- Add a leading zero if the first octet has a single hexadecimal character. IF MOD(length, 2) = 1 THEN hex := CONCAT('0', hex); length := length + 1; END IF; -- Start with the first octet. output := SUBSTR(hex, 1, 2); -- Add one octet at a time and a leading colon with each. WHILE i < length LOOP output := CONCAT(output, ':', SUBSTR(hex, i, 2)); i := i + 2; END LOOP; -- Memfile uses lowercase hexadecimals. output := LOWER(output); RETURN output; END \$\$ LANGUAGE plpgsql; -- Modify the function to output a memfile-ready CSV file. -- Some columns that are SMALLINT in the lease4 table have their type promoted -- to INT in the declaration of this function for backwards compatibility with -- PostgreSQL versions. DROP FUNCTION IF EXISTS lease4DumpData(); CREATE OR REPLACE FUNCTION lease4DumpData() RETURNS TABLE ( address INET, hwaddr VARCHAR, client_id VARCHAR, valid_lifetime BIGINT, expire BIGINT, subnet_id BIGINT, fqdn_fwd INT, fqdn_rev INT, hostname VARCHAR, state INT8, user_context VARCHAR ) AS \$\$ SELECT ('0.0.0.0'::inet + address), colonSeparatedHex(encode(hwaddr, 'hex')), colonSeparatedHex(encode(client_id, 'hex')), valid_lifetime, extract(epoch from expire)::bigint, subnet_id, fqdn_fwd::int, fqdn_rev::int, replace(hostname, ',', ','), state, replace(user_context, ',', ',') FROM lease4 ORDER BY address; \$\$ LANGUAGE SQL; -- hwtype and hwaddr_source need to be last to match memfile format. DROP FUNCTION IF EXISTS lease6DumpHeader(); CREATE OR REPLACE FUNCTION lease6DumpHeader() RETURNS TEXT AS \$\$ SELECT CAST('address,duid,valid_lifetime,expire,subnet_id,pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,state,user_context,hwtype,hwaddr_source' AS TEXT) AS result; \$\$ LANGUAGE SQL; -- Modify the function to output a memfile-ready CSV file. -- Some columns that are SMALLINT in the lease6 table have their type promoted -- to INT in the declaration of this function for backwards compatibility with -- PostgreSQL versions. DROP FUNCTION IF EXISTS lease6DumpData(); CREATE OR REPLACE FUNCTION lease6DumpData() RETURNS TABLE ( address VARCHAR, duid VARCHAR, valid_lifetime BIGINT, expire BIGINT, subnet_id BIGINT, pref_lifetime BIGINT, lease_type SMALLINT, iaid INT, prefix_len SMALLINT, fqdn_fwd INT, fqdn_rev INT, hostname VARCHAR, hwaddr VARCHAR, state INT8, user_context VARCHAR, hwtype SMALLINT, hwaddr_source SMALLINT ) AS \$\$ SELECT address, colonSeparatedHex(encode(duid, 'hex')), valid_lifetime, extract(epoch from expire)::bigint, subnet_id, pref_lifetime, lease_type, iaid, prefix_len, fqdn_fwd::int, fqdn_rev::int, replace(hostname, ',', ','), colonSeparatedHex(encode(hwaddr, 'hex')), state, replace(user_context, ',', ','), hwtype, hwaddr_source FROM lease6 ORDER BY address; \$\$ LANGUAGE SQL; -- Create a procedure that inserts a v4 lease from memfile data. -- Some columns that are SMALLINT in the lease4 table have their type promoted -- to INT in the declaration of this function for backwards compatibility with -- PostgreSQL versions. CREATE OR REPLACE FUNCTION lease4Upload( IN address VARCHAR, IN hwaddr VARCHAR, IN client_id VARCHAR, IN valid_lifetime BIGINT, IN expire BIGINT, IN subnet_id BIGINT, IN fqdn_fwd INT, IN fqdn_rev INT, IN hostname VARCHAR, IN state INT8, IN user_context VARCHAR ) RETURNS VOID AS \$\$ BEGIN INSERT INTO lease4 ( address, hwaddr, client_id, valid_lifetime, expire, subnet_id, fqdn_fwd, fqdn_rev, hostname, state, user_context ) VALUES ( address::inet - '0.0.0.0'::inet, decode(replace(hwaddr, ':', ''), 'hex'), decode(replace(client_id, ':', ''), 'hex'), valid_lifetime, to_timestamp(expire), subnet_id, fqdn_fwd::int::boolean, fqdn_rev::int::boolean, replace(hostname, ',', ','), state, replace(user_context, ',', ',') ); END \$\$ LANGUAGE plpgsql; -- Create a procedure that inserts a v6 lease from memfile data. -- Some columns that are SMALLINT in the lease6 table have their type promoted -- to INT in the declaration of this function for backwards compatibility with -- PostgreSQL versions. CREATE OR REPLACE FUNCTION lease6Upload( IN address VARCHAR, IN duid VARCHAR, IN valid_lifetime BIGINT, IN expire BIGINT, IN subnet_id BIGINT, IN pref_lifetime BIGINT, IN lease_type INT, IN iaid INT, IN prefix_len INT, IN fqdn_fwd INT, IN fqdn_rev INT, IN hostname VARCHAR, IN hwaddr VARCHAR, IN state INT8, IN user_context VARCHAR, IN hwtype INT, IN hwaddr_source INT ) RETURNS VOID AS \$\$ BEGIN INSERT INTO lease6 ( address, duid, valid_lifetime, expire, subnet_id, pref_lifetime, lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, state, user_context, hwtype, hwaddr_source ) VALUES ( address, decode(replace(duid, ':', ''), 'hex'), valid_lifetime, to_timestamp(expire), subnet_id, pref_lifetime, lease_type, iaid, prefix_len, fqdn_fwd::int::boolean, fqdn_rev::int::boolean, replace(hostname, ',', ','), decode(replace(hwaddr, ':', ''), 'hex'), state, replace(user_context, ',', ','), hwtype, hwaddr_source ); END \$\$ LANGUAGE plpgsql; -- Update the schema version number. UPDATE schema_version SET version = '8', minor = '0'; -- This line concludes the schema upgrade to version 8.0. -- Commit the script transaction. COMMIT; EOF