-- This is the core database schema for the Anvil! Intelligent Availability platform.
--
-- It expects PostgreSQL v. 9.1+
--
-- Table construction rules;
--
-- All tables need to have a column called '<table>_uuid uuid not null primary key' that will have a
-- unique UUID. This is used to keep track of the same entry in the history schema. If the table ends in a
-- plural, the '<table>_uuid' and can use the singular form of the table. For example, the table 'hosts' can
-- use 'host_uuid'.
--
-- All tables must hast a 'modified_date timestamp with time zone not null' column. This is used to track
-- changes through time in the history schema and used to groups changes when resync'ing.
--
-- Tables can optionally have a '*_host_uuid uuid not null' colum. If this is found, when resync'ing the
-- table, the resync will be restricted to the host's 'sys::host_uuid'.
--
-- Most tables will want to have a matching table in the history schema with an additional
-- 'history_id bigserial' column. Match the function and trigger seen elsewhere to copy your data from the
-- public schema to the history schema on UPDATE or INSERT.
--
-- If a table is a child of another table, ie: a UPS battery is a child of a UPS, and you have tables for
-- each that you plan to link, still use a '*_host_uuid' column (if the data is host-specific). This is
-- needed by the resync method.
SET client_encoding = ' UTF8 ' ;
-- This doesn't work before 9.3 - CREATE SCHEMA IF NOT EXISTS history;
-- So we'll use the query below until (if) we upgrade.
DO $ $
BEGIN
IF NOT EXISTS (
SELECT schema_name FROM information_schema . schemata WHERE schema_name = ' history '
)
THEN
EXECUTE ' CREATE SCHEMA history ' ;
END IF ;
END
$ $ ;
-- This stores information about the host machine. This is the master table that everything will be linked
-- to.
CREATE TABLE hosts (
host_uuid uuid not null primary key , -- This is the single most important record in ScanCore. Everything links back to here.
host_name text not null ,
host_type text not null , -- Either 'node' or 'dashboard'.
modified_date timestamp with time zone not null
) ;
ALTER TABLE hosts OWNER TO #!variable!user!#;
CREATE TABLE history . hosts (
history_id bigserial ,
host_uuid uuid not null ,
host_name text not null ,
host_type text not null ,
modified_date timestamp with time zone not null
) ;
ALTER TABLE history . hosts OWNER TO #!variable!user!#;
CREATE FUNCTION history_hosts ( ) RETURNS trigger
AS $ $
DECLARE
history_hosts RECORD ;
BEGIN
SELECT INTO history_hosts * FROM hosts WHERE host_uuid = new . host_uuid ;
INSERT INTO history . hosts
( host_uuid ,
host_name ,
host_type ,
modified_date )
VALUES
( history_hosts . host_uuid ,
history_hosts . host_name ,
history_hosts . host_type ,
history_hosts . modified_date ) ;
RETURN NULL ;
END ;
$ $
LANGUAGE plpgsql ;
ALTER FUNCTION history_hosts ( ) OWNER TO #!variable!user!#;
CREATE TRIGGER trigger_hosts
AFTER INSERT OR UPDATE ON hosts
FOR EACH ROW EXECUTE PROCEDURE history_hosts ( ) ;
-- This stores special variables for a given host that programs may want to record.
CREATE TABLE host_variable (
host_variable_uuid uuid not null primary key , -- This is the single most important record in ScanCore. Everything links back to here.
host_variable_host_uuid uuid not null ,
host_variable_name text not null ,
host_variable_value text ,
modified_date timestamp with time zone not null
) ;
ALTER TABLE host_variable OWNER TO #!variable!user!#;
CREATE TABLE history . host_variable (
history_id bigserial ,
host_variable_uuid uuid not null ,
host_variable_host_uuid uuid ,
host_variable_name text ,
host_variable_value text ,
modified_date timestamp with time zone not null
) ;
ALTER TABLE history . host_variable OWNER TO #!variable!user!#;
CREATE FUNCTION history_host_variable ( ) RETURNS trigger
AS $ $
DECLARE
history_host_variable RECORD ;
BEGIN
SELECT INTO history_host_variable * FROM host_variable WHERE host_uuid = new . host_uuid ;
INSERT INTO history . host_variable
( host_variable_uuid ,
host_variable_host_uuid ,
host_variable_name ,
host_variable_value ,
modified_date )
VALUES
( history_host_variable . host_variable_uuid ,
history_host_variable . host_variable_host_uuid ,
history_host_variable . host_variable_name ,
history_host_variable . host_variable_value ,
history_host_variable . modified_date ) ;
RETURN NULL ;
END ;
$ $
LANGUAGE plpgsql ;
ALTER FUNCTION history_host_variable ( ) OWNER TO #!variable!user!#;
CREATE TRIGGER trigger_host_variable
AFTER INSERT OR UPDATE ON host_variable
FOR EACH ROW EXECUTE PROCEDURE history_host_variable ( ) ;
-- This stores alerts coming in from various sources
CREATE TABLE alerts (
alert_uuid uuid not null primary key ,
alert_host_uuid uuid not null , -- The name of the node or dashboard that this alert came from.
alert_set_by text not null ,
alert_level text not null , -- debug (log only), info (+ admin email), notice (+ curious users), warning (+ client technical staff), critical (+ all)
alert_title_key text not null , -- ScanCore will read in the agents <name>.xml words file and look for this message key
alert_title_variables text , -- List of variables to substitute into the message key. Format is 'var1=val1 #!# var2 #!# val2 #!# ... #!# varN=valN'.
alert_message_key text not null , -- ScanCore will read in the agents <name>.xml words file and look for this message key
alert_message_variables text , -- List of variables to substitute into the message key. Format is 'var1=val1 #!# var2 #!# val2 #!# ... #!# varN=valN'.
alert_sort text , -- The alerts will sort on this column. It allows for an optional sorting of the messages in the alert.
alert_header boolean not null default TRUE , -- This can be set to have the alert be printed with only the contents of the string, no headers.
modified_date timestamp with time zone not null ,
FOREIGN KEY ( alert_host_uuid ) REFERENCES hosts ( host_uuid )
) ;
ALTER TABLE alerts OWNER TO #!variable!user!#;
CREATE TABLE history . alerts (
history_id bigserial ,
alert_uuid uuid ,
alert_host_uuid uuid ,
alert_set_by text ,
alert_level text ,
alert_title_key text ,
alert_title_variables text ,
alert_message_key text ,
alert_message_variables text ,
alert_sort text ,
alert_header boolean ,
modified_date timestamp with time zone not null
) ;
ALTER TABLE history . alerts OWNER TO #!variable!user!#;
CREATE FUNCTION history_alerts ( ) RETURNS trigger
AS $ $
DECLARE
history_alerts RECORD ;
BEGIN
SELECT INTO history_alerts * FROM alerts WHERE alert_uuid = new . alert_uuid ;
INSERT INTO history . alerts
( alert_uuid ,
alert_host_uuid ,
alert_set_by ,
alert_level ,
alert_title_key ,
alert_title_variables ,
alert_message_key ,
alert_message_variables ,
alert_sort ,
alert_header ,
modified_date )
VALUES
( history_alerts . alert_uuid ,
history_alerts . alert_host_uuid ,
history_alerts . alert_set_by ,
history_alerts . alert_level ,
history_alerts . alert_title_key ,
history_alerts . alert_title_variables ,
history_alerts . alert_message_key ,
history_alerts . alert_message_variables ,
history_alerts . alert_sort ,
history_alerts . alert_header ,
history_alerts . modified_date ) ;
RETURN NULL ;
END ;
$ $
LANGUAGE plpgsql ;
ALTER FUNCTION history_alerts ( ) OWNER TO #!variable!user!#;
CREATE TRIGGER trigger_alerts
AFTER INSERT OR UPDATE ON alerts
FOR EACH ROW EXECUTE PROCEDURE history_alerts ( ) ;
-- This holds user-configurable variable. These values override defaults but NOT configuration files.
CREATE TABLE variables (
variable_uuid uuid not null primary key ,
variable_name text not null , -- This is the 'x::y::z' style variable name.
variable_value text , -- It is up to the software to sanity check variable values before they are stored
variable_default text , -- This acts as a reference for the user should they want to roll-back changes.
variable_description text , -- This is a string key that describes this variable's use.
variable_section text , -- This is a free-form field that is used when displaying the various entries to a user. This allows for the various variables to be grouped into sections.
variable_source_uuid text , -- Optional; Marks the variable as belonging to a specific X_uuid, where 'X' is a table name set in 'variable_source_table'
variable_source_table text , -- Optional; Marks the database table corresponding to the 'variable_source_uuid' value.
modified_date timestamp with time zone not null
) ;
ALTER TABLE variables OWNER TO #!variable!user!#;
CREATE TABLE history . variables (
history_id bigserial ,
variable_uuid uuid ,
variable_name text ,
variable_value text ,
variable_default text ,
variable_description text ,
variable_section text ,
variable_source_uuid text ,
variable_source_table text ,
modified_date timestamp with time zone not null
) ;
ALTER TABLE history . variables OWNER TO #!variable!user!#;
CREATE FUNCTION history_variables ( ) RETURNS trigger
AS $ $
DECLARE
history_variables RECORD ;
BEGIN
SELECT INTO history_variables * FROM variables WHERE variable_uuid = new . variable_uuid ;
INSERT INTO history . variables
( variable_uuid ,
variable_name ,
variable_value ,
variable_default ,
variable_description ,
variable_section ,
variable_source_uuid ,
variable_source_table ,
modified_date )
VALUES
( history_variables . variable_uuid ,
history_variables . variable_name ,
history_variables . variable_value ,
history_variables . variable_default ,
history_variables . variable_description ,
history_variables . variable_section ,
history_variables . variable_source_uuid ,
history_variables . variable_source_table ,
history_variables . modified_date ) ;
RETURN NULL ;
END ;
$ $
LANGUAGE plpgsql ;
ALTER FUNCTION history_variables ( ) OWNER TO #!variable!user!#;
CREATE TRIGGER trigger_variables
AFTER INSERT OR UPDATE ON variables
FOR EACH ROW EXECUTE PROCEDURE history_variables ( ) ;
-- This holds jobs to be run.
CREATE TABLE jobs (
job_uuid uuid not null primary key , --
job_host_uuid uuid not null , -- This is the host that requested the job
job_type text not null , -- This indicates which daemon should run this job ('normal' = anvil_daemon, 'slow' = anvil_jobs)
job_name text not null , -- This is the 'x::y::z' style job name.
job_progress numeric not null , -- An "approximate" percentage completed
job_title text not null , -- This is a word key for the title of this job
job_description text not null , -- This is a word key that describes this job.
modified_date timestamp with time zone not null ,
FOREIGN KEY ( job_host_uuid ) REFERENCES hosts ( host_uuid )
) ;
ALTER TABLE jobs OWNER TO #!variable!user!#;
CREATE TABLE history . jobs (
history_id bigserial ,
job_uuid uuid ,
job_host_uuid uuid ,
job_type text ,
job_name text ,
job_progress numeric ,
job_title text ,
job_description text ,
modified_date timestamp with time zone not null
) ;
ALTER TABLE history . jobs OWNER TO #!variable!user!#;
CREATE FUNCTION history_jobs ( ) RETURNS trigger
AS $ $
DECLARE
history_jobs RECORD ;
BEGIN
SELECT INTO history_jobs * FROM jobs WHERE job_uuid = new . job_uuid ;
INSERT INTO history . jobs
( job_uuid ,
job_host_uuid ,
job_type ,
job_name ,
job_progress ,
job_title ,
job_description ,
modified_date )
VALUES
( history_jobs . job_uuid ,
history_jobs . job_host_uuid ,
history_jobs . job_type ,
history_jobs . job_name ,
history_jobs . job_progress ,
history_jobs . job_title ,
history_jobs . job_description ,
history_jobs . modified_date ) ;
RETURN NULL ;
END ;
$ $
LANGUAGE plpgsql ;
ALTER FUNCTION history_jobs ( ) OWNER TO #!variable!user!#;
CREATE TRIGGER trigger_jobs
AFTER INSERT OR UPDATE ON jobs
FOR EACH ROW EXECUTE PROCEDURE history_jobs ( ) ;
-- NOTE: network_interfaces, network_bonds and network_bridges are all used by scan-network (which doesn't
-- exist yet).
-- This stores information about network interfaces on hosts. It is mainly used to match a MAC address to a
-- host. Given that it is possible that network devices can move, the linkage to the host_uuid can change.
CREATE TABLE network_interfaces (
network_interface_uuid uuid not null primary key ,
network_interface_host_uuid uuid not null ,
network_interface_mac_address text not null ,
network_interface_name text not null , -- This is the current name of the interface.
network_interface_speed bigint not null , -- This is the speed, in bits-per-second, of the interface.
network_interface_mtu bigint , -- This is the MTU (Maximum Transmitable Size), in bytes, for this interface.
network_interface_link_state text not null , -- 0 or 1
network_interface_operational text not null , -- This is 'up', 'down' or 'unknown'
network_interface_duplex text not null , -- This is 'full', 'half' or 'unknown'
network_interface_medium text , -- This is 'tp' (twisted pair), 'fiber' or whatever they invent in the future.
network_interface_bond_uuid uuid , -- If this iface is in a bond, this will contain the 'bonds -> bond_uuid' that it is slaved to.
network_interface_bridge_uuid uuid , -- If this iface is attached to a bridge, this will contain the 'bridgess -> bridge_uuid' that it is connected to.
modified_date timestamp with time zone not null
) ;
ALTER TABLE network_interfaces OWNER TO #!variable!user!#;
CREATE TABLE history . network_interfaces (
history_id bigserial ,
network_interface_uuid uuid not null ,
network_interface_host_uuid uuid ,
network_interface_mac_address text ,
network_interface_name text ,
network_interface_speed bigint ,
network_interface_mtu bigint ,
network_interface_link_state text ,
network_interface_operational text ,
network_interface_duplex text ,
network_interface_medium text ,
network_interface_bond_uuid uuid ,
network_interface_bridge_uuid uuid ,
modified_date timestamp with time zone not null
) ;
ALTER TABLE history . network_interfaces OWNER TO #!variable!user!#;
CREATE FUNCTION history_network_interfaces ( ) RETURNS trigger
AS $ $
DECLARE
history_network_interfaces RECORD ;
BEGIN
SELECT INTO history_network_interfaces * FROM network_interfaces WHERE network_interface_host_uuid = new . network_interface_host_uuid ;
INSERT INTO history . network_interfaces
( network_interface_uuid ,
network_interface_host_uuid ,
network_interface_mac_address ,
network_interface_name ,
network_interface_speed ,
network_interface_mtu ,
network_interface_link_state ,
network_interface_operational ,
network_interface_duplex ,
network_interface_medium ,
network_interface_bond_uuid ,
network_interface_bridge_uuid ,
modified_date )
VALUES
( history_network_interfaces . network_interface_uuid ,
history_network_interfaces . network_interface_host_uuid ,
history_network_interfaces . network_interface_mac_address ,
history_network_interfaces . network_interface_name ,
history_network_interfaces . network_interface_speed ,
history_network_interfaces . network_interface_mtu ,
history_network_interfaces . network_interface_link_state ,
history_network_interfaces . network_interface_operational ,
history_network_interfaces . network_interface_duplex ,
history_network_interfaces . network_interface_medium ,
history_network_interfaces . network_interface_bond_uuid ,
history_network_interfaces . network_interface_bridge_uuid ,
history_network_interfaces . modified_date ) ;
RETURN NULL ;
END ;
$ $
LANGUAGE plpgsql ;
ALTER FUNCTION history_network_interfaces ( ) OWNER TO #!variable!user!#;
CREATE TRIGGER trigger_network_interfaces
AFTER INSERT OR UPDATE ON network_interfaces
FOR EACH ROW EXECUTE PROCEDURE history_network_interfaces ( ) ;
-- This stores information about network bonds (mode=1) on a hosts.
CREATE TABLE bonds (
bond_uuid uuid not null primary key ,
bond_host_uuid uuid not null ,
bond_name text not null ,
bond_mode integer not null , -- This is the numerical bond type (will translate to the user's language in ScanCore)
bond_mtu bigint ,
bond_primary_slave text ,
bond_primary_reselect text ,
bond_active_slave text ,
bond_mii_status text ,
bond_mii_polling_interval bigint ,
bond_up_delay bigint ,
bond_down_delay bigint ,
modified_date timestamp with time zone not null ,
FOREIGN KEY ( bond_host_uuid ) REFERENCES hosts ( host_uuid )
) ;
ALTER TABLE bonds OWNER TO #!variable!user!#;
CREATE TABLE history . bonds (
history_id bigserial ,
bond_uuid uuid ,
bond_host_uuid uuid ,
bond_name text ,
bond_mode integer ,
bond_mtu bigint ,
bond_primary_slave text ,
bond_primary_reselect text ,
bond_active_slave text ,
bond_mii_status text ,
bond_mii_polling_interval bigint ,
bond_up_delay bigint ,
bond_down_delay bigint ,
modified_date timestamp with time zone not null
) ;
ALTER TABLE history . bonds OWNER TO #!variable!user!#;
CREATE FUNCTION history_bonds ( ) RETURNS trigger
AS $ $
DECLARE
history_bonds RECORD ;
BEGIN
SELECT INTO history_bonds * FROM bonds WHERE bond_uuid = new . bond_uuid ;
INSERT INTO history . bonds
( bond_uuid ,
bond_host_uuid ,
bond_name ,
bond_mode ,
bond_mtu ,
bond_primary_slave ,
bond_primary_reselect ,
bond_active_slave ,
bond_mii_status ,
bond_mii_polling_interval ,
bond_up_delay ,
bond_down_delay ,
modified_date )
VALUES
( history_bonds . bond_uuid ,
history_bonds . bond_host_uuid ,
history_bonds . bond_name ,
history_bonds . bond_mode ,
history_bonds . bond_mtu ,
history_bonds . bond_primary_slave ,
history_bonds . bond_primary_reselect ,
history_bonds . bond_active_slave ,
history_bonds . bond_mii_status ,
history_bonds . bond_mii_polling_interval ,
history_bonds . bond_up_delay ,
history_bonds . bond_down_delay ,
history_bonds . modified_date ) ;
RETURN NULL ;
END ;
$ $
LANGUAGE plpgsql ;
ALTER FUNCTION history_bonds ( ) OWNER TO #!variable!user!#;
CREATE TRIGGER trigger_bonds
AFTER INSERT OR UPDATE ON bonds
FOR EACH ROW EXECUTE PROCEDURE history_bonds ( ) ;
-- This stores information about network bridges.
CREATE TABLE bridges (
bridge_uuid uuid not null primary key ,
bridge_host_uuid uuid not null ,
bridge_name text not null ,
bridge_id text ,
bridge_stp_enabled text ,
modified_date timestamp with time zone not null ,
FOREIGN KEY ( bridge_host_uuid ) REFERENCES hosts ( host_uuid )
) ;
ALTER TABLE bridges OWNER TO #!variable!user!#;
CREATE TABLE history . bridges (
history_id bigserial ,
bridge_uuid uuid ,
bridge_host_uuid uuid ,
bridge_name text ,
bridge_id text ,
bridge_stp_enabled text ,
modified_date timestamp with time zone not null
) ;
ALTER TABLE history . bridges OWNER TO #!variable!user!#;
CREATE FUNCTION history_bridges ( ) RETURNS trigger
AS $ $
DECLARE
history_bridges RECORD ;
BEGIN
SELECT INTO history_bridges * FROM bridges WHERE bridge_uuid = new . bridge_uuid ;
INSERT INTO history . bridges
( bridge_uuid ,
bridge_host_uuid ,
bridge_name ,
bridge_name ,
bridge_id ,
bridge_stp_enabled ,
modified_date )
VALUES
( history_bridges . bridge_uuid ,
history_bridges . bridge_host_uuid ,
history_bridges . bridge_name ,
history_bridges . bridge_name ,
history_bridges . bridge_id ,
history_bridges . bridge_stp_enabled ,
history_bridges . modified_date ) ;
RETURN NULL ;
END ;
$ $
LANGUAGE plpgsql ;
ALTER FUNCTION history_bridges ( ) OWNER TO #!variable!user!#;
CREATE TRIGGER trigger_bridges
AFTER INSERT OR UPDATE ON bridges
FOR EACH ROW EXECUTE PROCEDURE history_bridges ( ) ;
-- ------------------------------------------------------------------------------------------------------- --
-- These are special tables with no history or tracking UUIDs that simply record transient information. --
-- ------------------------------------------------------------------------------------------------------- --
-- This table records the last time a scan ran. It's sole purpose is to make sure at least one table's
-- 'modified_date' changes per run, so that database resyncs can be triggered reliably.
CREATE TABLE updated (
updated_host_uuid uuid not null ,
updated_by text not null , -- The name of the agent (or "ScanCore' itself) that updated.
modified_date timestamp with time zone not null ,
FOREIGN KEY ( updated_host_uuid ) REFERENCES hosts ( host_uuid )
) ;
ALTER TABLE updated OWNER TO #!variable!user!#;
-- To avoid "waffling" when a sensor is close to an alert (or cleared) threshold, a gap between the alarm
-- value and the clear value is used. If the sensor climbs above (or below) the "clear" value, but didn't
-- previously pass the "alert" threshold, we DON'T want to send an "all clear" message. So do solve that,
-- this table is used by agents to record when a warning message was sent.
CREATE TABLE alert_sent (
alert_sent_uuid uuid not null primary key ,
alert_sent_host_uuid uuid not null , -- The node associated with this alert
alert_set_by text not null , -- name of the program that set this alert
alert_record_locator text not null , -- String used by the agent to identify the source of the alert (ie: UPS serial number)
alert_name text not null , -- A free-form name used by the caller to identify this alert.
modified_date timestamp with time zone not null ,
FOREIGN KEY ( alert_sent_host_uuid ) REFERENCES hosts ( host_uuid )
) ;
ALTER TABLE updated OWNER TO #!variable!user!#;
-- This stores state information, like the whether migrations are happening and so on.
CREATE TABLE states (
state_uuid uuid not null primary key ,
state_name text not null , -- This is the name of the state (ie: 'migration', etc)
state_host_uuid uuid not null , -- The UUID of the machine that the state relates to. In migrations, this is the UUID of the target
state_note text , -- This is a free-form note section that the application setting the state can use for extra information (like the name of the server being migrated)
modified_date timestamp with time zone not null ,
FOREIGN KEY ( state_host_uuid ) REFERENCES hosts ( host_uuid )
) ;
ALTER TABLE states OWNER TO #!variable!user!#;