#!/bin/sh # Copyright (C) 2014-2023 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/. # shellcheck disable=SC1091 # SC1091: Not following: ... was not specified as input (see shellcheck -x). # shellcheck disable=SC2039 # SC2039: In POSIX sh, 'local' is undefined. # Exit with error if commands exit with non-zero and if undefined variables are # used. set -eu # Include common test library. . "@abs_top_builddir@/src/lib/testutils/dhcp_test_lib.sh" # Locations of memfile tools kea_admin="@abs_top_builddir@/src/bin/admin/kea-admin" kea_lfc="@abs_top_builddir@/src/bin/lfc/kea-lfc" # Clean up any files used in testing. clean_up() { remove_if_exists \ "${config_file-}" \ "${csv-}" \ "${csv_2-}" \ "@abs_top_builddir@/src/bin/admin/tests/kea.log" \ "@abs_top_builddir@/src/bin/admin/tests/kea.log.lock" } # Print location of CSV file. Accepts 4 or 6 as parameter. csv_file() { local v="${1}" printf '%s' "@abs_top_builddir@/src/bin/admin/tests/kea-dhcp${v}.csv" } # Print location of kea-dhcp[46] binaries. Accepts 4 or 6 as parameter. kea_dhcp() { local v="${1}" printf '%s' "@abs_top_builddir@/src/bin/dhcp${v}/kea-dhcp${v}" } # Print the minimum allowed number of header columns for v4. incomplete_memfile_header_v4() { printf 'address,hwaddr,client_id,valid_lifetime,expire,subnet_id,fqdn_fwd,fqdn_rev,hostname' } # Print the minimum allowed number of header columns for v6. incomplete_memfile_header_v6() { printf 'address,duid,valid_lifetime,expire,subnet_id,pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname' } # Print the entire header for v4. memfile_header_v4() { printf '%s,state,user_context,pool_id' "$(incomplete_memfile_header_v4)" } # Print the entire header for v6. memfile_header_v6() { printf '%s,hwaddr,state,user_context,hwtype,hwaddr_source,pool_id' "$(incomplete_memfile_header_v6)" } # Print data copied from mysql_upgrade_12_to_13_test and pgsql_upgrade_7_0_to_8_0. # @{ memfile_data_v4() { printf '0.0.0.10,32:30,33:30,40,1678900000,50,1,1,oneˎxampleˌom,0,{"a":1,"b":2},0' } memfile_data_v6() { printf '::10,32:30:33,30,1678900000,40,50,1,60,70,1,1,oneˎxampleˌom,38:30,0,{"a":1,"b":2},90,16,0' } # @} # Print "server-id" configuration. Not available for v4. server_id_v4() { : } # Print "server-id" configuration. Not available for v4. server_id_v6() { printf ', "server-id": { "persist": false, "type": "EN" } ' } # Starts Kea and sets PID. It logs to stdout and stderr if DEBUG is enabled. # Accepts 4 or 6 as parameter. start_kea_dhcp() { local v="${1}" "$(kea_dhcp "${v}")" -c "${config_file}" >> "@abs_top_builddir@/src/bin/admin/tests/kea.log" 2>&1 & PID=${!} sleep 1 } # Test that Kea creates a correctly populated CSV file if configured with # persisting memfile. memfile_init_test() { test_start 'memfile.init' for v in 4 6; do for i in no-file some-data; do if test -n "${DEBUG+x}"; then printf 'TRACE %s, %s\n' "${v}" "${i}" fi config=$(printf '%s%s%s' ' { "Dhcpx": { "lease-database": { "name": "@abs_top_builddir@/src/bin/admin/tests/kea-dhcpx.csv", "persist": true, "type": "memfile" }, "loggers": [ { "debuglevel": 99, "name": "kea-dhcpx", "output_options": [ { "output": "@abs_top_builddir@/src/bin/admin/tests/kea.log" } ], "severity": "DEBUG" } ]' \ "$(server_id_v${v})" \ ' } } ') config_file="@abs_top_builddir@/src/bin/admin/tests/kea-dhcp${v}.conf" csv=$(csv_file "${v}") if test "${i}" = 'some-data'; then # Test that Kea accepts the output of lease-dump in memfile. { "memfile_header_v${v}" printf '\n' "memfile_data_v${v}" printf '\n' } > "${csv}" else # Make sure there is no CSV as the test requires. rm -f "${csv}" fi # Set DHCP version in config. printf '%s\n' "${config}" | \ sed "s#Dhcpx#Dhcp${v}#g; s#dhcpx#dhcp${v}#g" \ > "${config_file}" start_kea_dhcp "${v}" # This assumes that the CSV creation + writing to CSV is atomic. Not # sure if it is, but if this ever fails on the comparison further below, # consider waiting here for line DHCPSRV_MEMFILE_LFC_SETUP in logs, even # though it doesn't clearly signal end of CSV writing. if ! wait_for_file "${csv}"; then clean_up clean_exit 1 fi kill "${PID}" || true # process may have exited early due to errors if ! wait_for_process_to_stop "${PID}"; then clean_up clean_exit 2 fi content=$(head -n 1 "${csv}") expected=$(memfile_header_v${v}) if test "${content}" != "${expected}"; then printf 'ERROR: %s does not contain expected header.\n< %s\n> %s\n' \ "${csv}" "${content}" "${expected}" >&2 clean_up clean_exit 3 fi if grep -Fi ERROR "@abs_top_builddir@/src/bin/admin/tests/kea.log"; then printf 'ERROR: loading memfile failed. See error above.\n' >&2 cat "${csv}" clean_up clean_exit 4 fi clean_up done done test_finish 0 } # Test that kea-lfc is able to upgrade a CSV file with incomplete header. memfile_upgrade_test() { test_start 'memfile.upgrade' for v in 4 6; do csv=$(csv_file "${v}") "incomplete_memfile_header_v${v}" > "${csv}" printf '\n' >> "${csv}" csv_2="${csv}.2" "${kea_lfc}" "-${v}" \ -c 'ignored-path' \ -f "${csv}.completed" \ -i "${csv}" \ -o "${csv}.output" \ -p "${csv}.pid" \ -x "${csv_2}" content=$(cat "${csv_2}") expected=$(memfile_header_v${v}) if test "${content}" != "${expected}"; then printf 'ERROR: %s does not contain expected header.\n< %s\n> %s\n' \ "${csv}" "${content}" "${expected}" >&2 clean_up clean_exit 1 fi clean_up done test_finish 0 } # shellcheck disable=SC2034 # SC2034: ... appears unused. Verify use (or export if used externally). # reason: bin and bin_path are used in version_test { bin=$(basename "${kea_admin}") bin_path=$(dirname "${kea_admin}") version_test 'memfile.version' 'long_version_too_please' } memfile_init_test memfile_upgrade_test