From 085240828b8c35189d5f174683f7bca4e503c90c Mon Sep 17 00:00:00 2001 From: Yonas Habteab Date: Tue, 14 Nov 2023 12:15:06 +0100 Subject: [PATCH] Fail migrating schedule config when named timezones aren't loaded --- doc/80-Upgrading.md | 19 +++++++++++++++++-- schema/mysql-upgrades/1.0.0.sql | 18 +++++++++++++++++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/doc/80-Upgrading.md b/doc/80-Upgrading.md index a2f8067..39ea37b 100644 --- a/doc/80-Upgrading.md +++ b/doc/80-Upgrading.md @@ -6,10 +6,25 @@ Usually the only manual steps involved are schema updates for the database. ## Upgrading to Version 1.0.0 Icinga Reporting version 1.0.0 requires a schema update for the database. + +> **Note** +> +> In order for the migration script to be successful, you must [populate](https://dev.mysql.com/doc/refman/8.0/en/time-zone-support.html#time-zone-installation) +> all the system named time zone information into your MSQL/MariaDB server. Otherwise, the migration will not succeed +> and will produce an SQL error. + If you're already using Icinga Web version `>= 2.12`, then you don't need to perform any of these steps manually. Icinga Web provides you the ability to perform such migrations in a simple way. You may be familiar with such an -automation if you're an Icinga Director user. For those who are not using the latest version of Icinga Web, please -follow the instructions below. +automation if you're an Icinga Director user. + +> **Note** +> +> Icinga Reporting `1.0.0` upgrade script requires some timezone information from the `mysql.time_zone_name` +> table in order to migrate any data. Therefore, the user must be explicitly granted the `SELECT` privilege +> on this table when running the upgrade script with a non-root user using the following command: +> `GRANT SELECT ON mysql.time_zone_name TO 'reporting'@'localhost';` + +For those who are not using the latest version of Icinga Web, please follow the instructions below. You may use the following command to apply the database schema upgrade file: diff --git a/schema/mysql-upgrades/1.0.0.sql b/schema/mysql-upgrades/1.0.0.sql index 5635e0e..169d731 100644 --- a/schema/mysql-upgrades/1.0.0.sql +++ b/schema/mysql-upgrades/1.0.0.sql @@ -2,6 +2,10 @@ DROP PROCEDURE IF EXISTS migrate_schedule_config; DELIMITER // CREATE PROCEDURE migrate_schedule_config() BEGIN + DECLARE session_time_zone text; + DECLARE session_time_zone_exists text; + DECLARE utc_time_zone text; + DECLARE schedule_id int; DECLARE schedule_start bigint; DECLARE schedule_frequency enum('minutely', 'hourly', 'daily', 'weekly', 'monthly'); @@ -13,6 +17,18 @@ BEGIN DECLARE schedule CURSOR FOR SELECT id, start, frequency, config FROM schedule; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; + -- Determine the current session time zone name + SELECT IF(@@session.TIME_ZONE = 'SYSTEM', @@system_time_zone, @@session.TIME_ZONE) INTO session_time_zone; + + IF session_time_zone NOT LIKE '+%:%' THEN + SELECT Name INTO session_time_zone_exists FROM mysql.time_zone_name WHERE Name = session_time_zone LIMIT 1; + END IF; + + SELECT Name INTO utc_time_zone FROM mysql.time_zone_name WHERE Name = 'UTC' LIMIT 1; + IF utc_time_zone IS NULL OR (session_time_zone NOT LIKE '+%:%' AND session_time_zone_exists IS NULL) THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'required named time zone information are not populated into mysql/mariadb'; + END IF; + OPEN schedule; read_loop: LOOP FETCH schedule INTO schedule_id, schedule_start, schedule_frequency, schedule_config; @@ -23,7 +39,7 @@ BEGIN SET frequency_json = CONCAT( ',"frequencyType":"\\\\ipl\\\\Scheduler\\\\Cron","frequency":"{', '\\"expression\\":\\"@', schedule_frequency, - '\\",\\"start\\":\\"', DATE_FORMAT(CONVERT_TZ(FROM_UNIXTIME(schedule_start / 1000), @@session.TIME_ZONE, 'UTC'), '%Y-%m-%dT%H:%i:%s.%f UTC'), + '\\",\\"start\\":\\"', DATE_FORMAT(CONVERT_TZ(FROM_UNIXTIME(schedule_start / 1000), session_time_zone, utc_time_zone), '%Y-%m-%dT%H:%i:%s.%f UTC'), '\\"}"' ); UPDATE schedule SET config = INSERT(schedule_config, LENGTH(schedule_config), 0, frequency_json) WHERE id = schedule_id;