From 74a09909973d3d75c73a25c81dd6cbef0e71cc04 Mon Sep 17 00:00:00 2001 From: Will Nilges Date: Mon, 4 Oct 2021 00:55:23 -0400 Subject: [PATCH] Fix hardcoded variables, tweak schema/dockerfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change config.local.py to config_local.py Fix 2AM Willard Moments™ Made a few errors last night that should be corrected. --- .gitignore | 2 + README.md | 2 +- config.py | 5 + developing/README.md | 26 +- developing/proxstar-postgres/Dockerfile | 2 + .../schema/proxstar/proxstar_schema_willard | Bin 16384 -> 0 bytes developing/schema/proxstar/toc.dat | Bin 7261 -> 0 bytes developing/schema/starrs/old/harmon_starrs.db | 18793 ---------------- developing/schema/starrs/old/starrs_schema | Bin 1085440 -> 0 bytes .../schema/starrs/old/starrs_schema_plpython2 | Bin 1082880 -> 0 bytes developing/schema/starrs/old/toc.dat | Bin 568569 -> 0 bytes .../schema/starrs/{old => }/restore.sql | 0 .../schema/starrs/starrs_schema_willard2 | Bin 1082880 -> 0 bytes gunicorn_conf.py | 4 +- proxstar/__init__.py | 2 + proxstar/proxmox.py | 3 +- proxstar/tasks.py | 9 +- proxstar/vm.py | 4 +- 18 files changed, 38 insertions(+), 18814 deletions(-) delete mode 100644 developing/schema/proxstar/proxstar_schema_willard delete mode 100644 developing/schema/proxstar/toc.dat delete mode 100644 developing/schema/starrs/old/harmon_starrs.db delete mode 100644 developing/schema/starrs/old/starrs_schema delete mode 100644 developing/schema/starrs/old/starrs_schema_plpython2 delete mode 100644 developing/schema/starrs/old/toc.dat rename developing/schema/starrs/{old => }/restore.sql (100%) delete mode 100644 developing/schema/starrs/starrs_schema_willard2 diff --git a/.gitignore b/.gitignore index 6fadd22..2cf59b2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ +config_local.py config.local.py +.env __pycache__/* */__pycache__/* rrd/* diff --git a/README.md b/README.md index 48accc2..e252204 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ It is available to house members at [proxstar.csh.rit.edu](https://proxstar.csh. 1. [Fork](https://help.github.com/en/articles/fork-a-repo) this repository - Optionally create a new [git branch](https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell) if your change is more than a small tweak (`git checkout -b BRANCH-NAME-HERE`) 3. Make your changes locally, commit, and push to your fork - - If you want to test locally, you should copy `config.py` to `config.local.py`, and talk to an RTP about filling in secrets. + - If you want to test locally, you should copy `config.py` to `config_local.py`, and talk to an RTP about filling in secrets. - Lint and format your local changes with `pylint proxstar` and `black proxstar` - You'll need dependencies installed locally to do this. You should do that in a [venv](https://packaging.python.org/tutorials/installing-packages/#creating-virtual-environments) of some sort to keep your system clean. All the dependencies are listed in [requirements.txt](./requirements.txt), so you can install everything with `pip install -r requirements.txt`. You'll need python 3.6 at minimum, though things should work up to python 3.8. 4. Create a [Pull Request](https://help.github.com/en/articles/about-pull-requests) on this repo for our Webmasters to review diff --git a/config.py b/config.py index 3b7ac53..cefda7f 100644 --- a/config.py +++ b/config.py @@ -4,6 +4,10 @@ from os import environ VM_EXPIRE_MONTHS = int(environ.get('PROXSTAR_VM_EXPIRE_MONTHS', '3')) VNC_CLEANUP_TOKEN = environ.get('PROXSTAR_VNC_CLEANUP_TOKEN', '') +# Development options +USE_STARRS = environ.get('PROXSTAR_USE_STARRS', 'True') +FORCE_STANDARD_USER = environ.get('PROXSTAR_FORCE_STANDARD_USER', 'False') + # Flask IP = environ.get('PROXSTAR_IP', '0.0.0.0') PORT = environ.get('PROXSTAR_PORT', '5000') @@ -25,6 +29,7 @@ PROXMOX_HOSTS = [host.strip() for host in environ.get('PROXSTAR_PROXMOX_HOSTS', PROXMOX_USER = environ.get('PROXSTAR_PROXMOX_USER', '') PROXMOX_PASS = environ.get('PROXSTAR_PROXMOX_PASS', '') PROXMOX_ISO_STORAGE = environ.get('PROXSTAR_PROXMOX_ISO_STORAGE', 'nfs-iso') +PROXMOX_VM_STORAGE = environ.get('PROXSTAR_PROXMOX_VM_STORAGE', 'ceph') PROXMOX_SSH_USER = environ.get('PROXSTAR_PROXMOX_SSH_USER', '') PROXMOX_SSH_KEY = environ.get('PROXSTAR_PROXMOX_SSH_KEY', '') PROXMOX_SSH_KEY_PASS = environ.get('PROXSTAR_PROXMOX_SSH_KEY_PASS', '') diff --git a/developing/README.md b/developing/README.md index 24b2635..2784eb8 100644 --- a/developing/README.md +++ b/developing/README.md @@ -11,7 +11,7 @@ If you want to work on Proxstar using a 1:1 development setup, there are a coupl 1. Configure your Proxmox node -I would recommend setting up a development account on your Proxmox node. Name it anything. (Maybe `proxstartest`?). This is necessary to grab authentication tokens and the like. It should have the same permissions as `root@pam`. If you do this, then it's easy to enable/disable it for development. You should also generate an SSH key for the user. +I would recommend setting up a development account on your Proxmox node. Name it anything. (Maybe `proxstartest`?). This is necessary to grab authentication tokens and the like. It should have the same permissions as `root@pam`. You can accomplish this by creating a group in `Datacenter > Permissions > Groups` and adding `Administrator` permissions to the group, then adding your user to the group. If you do this, then it's easy to enable/disable it for development. You should also generate an SSH key for the user. You will also have to set up a pool on your Proxmox node with your csh username. To do this, go into `Datacenter > Permissions > Pools > Create`. @@ -30,10 +30,10 @@ pip install -r requirements.txt pip install click==7.1.2 pip install python-dotenv ``` -Fill out the required fields in your config.local.py file. Some of this you might have to come back to after you run the docker compose. +Fill out the required fields in your config_local.py file. Some of this you might have to come back to after you run the docker compose. ``` -cp config.py config.local.py -vim config.local.py +cp config.py config_local.py +vim config_local.py ``` (Here's some advice on how to fill out your config file.) @@ -178,14 +178,18 @@ docker-compose up -d Restore the databse in your new podman container. This might throw a TON of errors, but don't worry about it. ``` -psql postgresql://postgres:********@10.69.69.69 - CREATE DATABASE proxstar; - CREATE DATABASE starrs; - quit; +echo 'CREATE DATABASE proxstar; CREATE DATABASE starrs; CREATE ROLE proxstar; CREATE ROLE starrs;' | psql postgresql://postgres:********@10.69.69.69 -pg_restore -U postgres -d proxstar -1 proxstar_schema_willard -h localhost -psql postgresql://postgres:tits12348@10.10.51.185/starrs < harmon_starrs.db -# psql postgresql://postgres:tits12348@10.10.51.185/proxstar < restore_proxstar.sql # Probably unnecessary +cat developing/schema/starrs/restore.sql | psql postgresql://postgres:********@10.69.69.69 +cat developing/schema/proxstar/restore.sql | psql postgresql://postgres:********@10.69.69.69 +``` + +Get a shell in your postgres real quick and install a perl thing. + +``` +docker exec -it developing_proxstar-postgres_1 bash +cpan +install Data::Validate::Domain ``` Now, you should be ready to run your dev instance. I like to use `tmux` for this to run proxstar and the `rq worker` in separate panes. diff --git a/developing/proxstar-postgres/Dockerfile b/developing/proxstar-postgres/Dockerfile index 554d6e5..c0d8f4a 100644 --- a/developing/proxstar-postgres/Dockerfile +++ b/developing/proxstar-postgres/Dockerfile @@ -3,4 +3,6 @@ FROM postgres:12 RUN apt-get update \ && apt-get install -y postgresql-plperl-12 \ && apt-get install -y postgresql-plpython3-12 \ + && apt-get install -y libnet-ip-perl perl-net libnet-ldap-perl libnet-dns-perl libnet-snmp-perl libnet-server-mail-perl libcrypt-des-perl \ + && apt-get install -y libperl-dev build-essential \ && rm -rf /var/lib/apt/lists/* diff --git a/developing/schema/proxstar/proxstar_schema_willard b/developing/schema/proxstar/proxstar_schema_willard deleted file mode 100644 index adb3469b9b9337a509b9575b72302b0c28d9b138..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 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 diff --git a/developing/schema/proxstar/toc.dat b/developing/schema/proxstar/toc.dat deleted file mode 100644 index 16472cd918980d323ddbc6d250fa4f7f07d13e9e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7261 zcmcJTZI9bT5P;oMN;#l_co9Mf773A5w8tg6%iXoAz)gI20mli6LpcywZsO+LI!JBJriXe&dJmBX}z>KL}=L?bvItb0MLY&gb>)%+5SJJG)MMx87`@Ixn3$_lSho z7QMg5p5cCqK0Quv_vj6q=ip)DjgS4n^rSP;D3w>M@x#ls z+^OxgWqptN6*ti@IzwGWRcbn!42`}Sn9g{(>RSOiXb+18-!i@afiW?IgTh5pfIozC zVIh9sPW@z4T`eQ#O1V_7;2cg$*5zw*SCP=w&*4q2qsY2KA_0lIlj{wAkLXIX zty1|_5?G^&V+Ph5iBe=b@kFf|wU!!oELg75>#jmdT-qw2NZ)T$3!LD}iu4k7sMBg^ z2N#oI;f(!Y=vlrnnZBFCNT&6(iNL4vNpwNUHI=QIi_qBZ$eK=MRV6Jg>k`phQ(dup zEU78wNybN9ewEGgRwDE7;~YSD6qc){c;+^xv($_;u{=k54j$W`R!yn*I=Fp0) zuMoH*WTcNxxl0OfIQET!?Y+&c(Pb#G3zb8nnSr$C@*~U)Hht)C%jGWdv%X8m^}%bO^!W+bHWeB~rvZvInGpV0vahusm{PdiP+@ zDOSoCh}P1H)>G9Lh(($%w|slqtcfEyu*?a|oM=lI?V`Uh1-NIUu3*&m&>eda^<+GD z=8l?E`X8d^>@6SluQQ^q;^s`Fh1JqOu&@v%CYqKi(L~1@VZ8Lk3G;jr)8T03!zOtg zeDdiu0hqu&92rz-yMZ-?REg4qNe_J}SLBvIc2fe!9@&8}lEAjmhZ9&zhS^5XXt>t6 zY>R_h9{O+j&^OqLBRVOhk^hu~JnA1On3$Anj;y(6g05`rOs6A7bz=Jd-LW^osY=NP zwtqV_ONjLqA=b$8<)QvQ1M0T)G)SYd40~Ys)*UPfUFCxw9LB=ZbsXc31X1-$DPy{J zb-AOnQ(g&QG&EQbO$E+C*Y*i}rL{=2p?xT;Jq5eaw)|1tuF17Mg_NMmy%_;IVdyNX z^ahzJb9hoKuWevQ#_4+95n*q;Qc)FO756 z9)$5Q-|)~T-1YN&$kd&iq3U!FbWd zRj#hB<63}U3@U3_W}@;(?1A(cbg3&la!=J+)w~5SSX}Ic(bClYbX|mxXj)d`CxKp5 z11nHqbrM=3F6_xirc*44i*4cZWzQP+9oVMn>G^VMxRg?6B+Qp^sKryFD%f+RX=-G! zm856DO>WAB?1EG>8Y+q|>@cW?L&~)4-BwE4qGLtibrAn^XAweSxgzJD~z>g@6rrg;l?<@PH zXb)&MzBlg>1oLpF{cLuE@$lEvoDaSbWjV2!&*Y=5AWH6&i*T*QP;w?jD7g*`q2w%N zP;yeVzc|WD0_E9!l=H7xy*R$jM6NxVk8cwz9>1$`t$c*DHV@8(2qM=Z U7vrqWgR_tU$w`+)nb?Q_1#)X$ssI20 diff --git a/developing/schema/starrs/old/harmon_starrs.db b/developing/schema/starrs/old/harmon_starrs.db deleted file mode 100644 index 2392e70..0000000 --- a/developing/schema/starrs/old/harmon_starrs.db +++ /dev/null @@ -1,18793 +0,0 @@ --- --- PostgreSQL database dump --- - -SET statement_timeout = 0; -SET client_encoding = 'UTF8'; -SET standard_conforming_strings = on; -SET check_function_bodies = false; -SET client_min_messages = warning; - --- --- Name: starrs; Type: COMMENT; Schema: -; Owner: starrs_admin --- - -COMMENT ON DATABASE starrs IS 'STARRS network management application'; - - --- --- Name: api; Type: SCHEMA; Schema: -; Owner: starrs_admin --- - -CREATE SCHEMA api; - - -ALTER SCHEMA api OWNER TO starrs_admin; - --- --- Name: SCHEMA api; Type: COMMENT; Schema: -; Owner: starrs_admin --- - -COMMENT ON SCHEMA api IS 'Interaction with clients'; - - --- --- Name: dhcp; Type: SCHEMA; Schema: -; Owner: starrs_admin --- - -CREATE SCHEMA dhcp; - - -ALTER SCHEMA dhcp OWNER TO starrs_admin; - --- --- Name: SCHEMA dhcp; Type: COMMENT; Schema: -; Owner: starrs_admin --- - -COMMENT ON SCHEMA dhcp IS 'Configuration for stateful addressing'; - - --- --- Name: dns; Type: SCHEMA; Schema: -; Owner: starrs_admin --- - -CREATE SCHEMA dns; - - -ALTER SCHEMA dns OWNER TO starrs_admin; - --- --- Name: SCHEMA dns; Type: COMMENT; Schema: -; Owner: starrs_admin --- - -COMMENT ON SCHEMA dns IS 'All DNS records for the controlled zones/domains'; - - --- --- Name: ip; Type: SCHEMA; Schema: -; Owner: starrs_admin --- - -CREATE SCHEMA ip; - - -ALTER SCHEMA ip OWNER TO starrs_admin; - --- --- Name: SCHEMA ip; Type: COMMENT; Schema: -; Owner: starrs_admin --- - -COMMENT ON SCHEMA ip IS 'Network resources available for devices'; - - --- --- Name: libvirt; Type: SCHEMA; Schema: -; Owner: starrs_admin --- - -CREATE SCHEMA libvirt; - - -ALTER SCHEMA libvirt OWNER TO starrs_admin; - --- --- Name: SCHEMA libvirt; Type: COMMENT; Schema: -; Owner: starrs_admin --- - -COMMENT ON SCHEMA libvirt IS 'Libvirt interaction with VM hosts'; - - --- --- Name: management; Type: SCHEMA; Schema: -; Owner: starrs_admin --- - -CREATE SCHEMA management; - - -ALTER SCHEMA management OWNER TO starrs_admin; - --- --- Name: SCHEMA management; Type: COMMENT; Schema: -; Owner: starrs_admin --- - -COMMENT ON SCHEMA management IS 'Application configuration and data'; - - --- --- Name: network; Type: SCHEMA; Schema: -; Owner: starrs_admin --- - -CREATE SCHEMA network; - - -ALTER SCHEMA network OWNER TO starrs_admin; - --- --- Name: SCHEMA network; Type: COMMENT; Schema: -; Owner: starrs_admin --- - -COMMENT ON SCHEMA network IS 'Data on special network devices'; - - --- --- Name: systems; Type: SCHEMA; Schema: -; Owner: starrs_admin --- - -CREATE SCHEMA systems; - - -ALTER SCHEMA systems OWNER TO starrs_admin; - --- --- Name: SCHEMA systems; Type: COMMENT; Schema: -; Owner: starrs_admin --- - -COMMENT ON SCHEMA systems IS 'User machine data for devices on the network'; - - --- --- Name: plperl; Type: PROCEDURAL LANGUAGE; Schema: -; Owner: starrs_admin --- - -CREATE OR REPLACE PROCEDURAL LANGUAGE plperl; - - -ALTER PROCEDURAL LANGUAGE plperl OWNER TO starrs_admin; - --- --- Name: plperlu; Type: PROCEDURAL LANGUAGE; Schema: -; Owner: postgres --- - -CREATE OR REPLACE PROCEDURAL LANGUAGE plperlu; - - -ALTER PROCEDURAL LANGUAGE plperlu OWNER TO postgres; - --- --- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: --- - -CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog; - - --- --- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: --- - -COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language'; - - --- --- Name: plpython2u; Type: PROCEDURAL LANGUAGE; Schema: -; Owner: postgres --- - -CREATE OR REPLACE PROCEDURAL LANGUAGE plpython2u; - - -ALTER PROCEDURAL LANGUAGE plpython2u OWNER TO postgres; - -SET search_path = dhcp, pg_catalog; - --- --- Name: dhcpd_class_options; Type: TYPE; Schema: dhcp; Owner: starrs_admin --- - -CREATE TYPE dhcpd_class_options AS ( - option text, - value text -); - - -ALTER TYPE dhcp.dhcpd_class_options OWNER TO starrs_admin; - --- --- Name: TYPE dhcpd_class_options; Type: COMMENT; Schema: dhcp; Owner: starrs_admin --- - -COMMENT ON TYPE dhcpd_class_options IS 'Get class options for the dhcpd.conf'; - - --- --- Name: dhcpd_classes; Type: TYPE; Schema: dhcp; Owner: starrs_admin --- - -CREATE TYPE dhcpd_classes AS ( - class text, - comment text -); - - -ALTER TYPE dhcp.dhcpd_classes OWNER TO starrs_admin; - --- --- Name: TYPE dhcpd_classes; Type: COMMENT; Schema: dhcp; Owner: starrs_admin --- - -COMMENT ON TYPE dhcpd_classes IS 'Class information for dhcpd.conf'; - - --- --- Name: dhcpd_dns_keys; Type: TYPE; Schema: dhcp; Owner: starrs_admin --- - -CREATE TYPE dhcpd_dns_keys AS ( - keyname text, - key text, - enctype text -); - - -ALTER TYPE dhcp.dhcpd_dns_keys OWNER TO starrs_admin; - --- --- Name: TYPE dhcpd_dns_keys; Type: COMMENT; Schema: dhcp; Owner: starrs_admin --- - -COMMENT ON TYPE dhcpd_dns_keys IS 'Get all dns key information for dhcpd'; - - --- --- Name: dhcpd_dynamic_hosts; Type: TYPE; Schema: dhcp; Owner: starrs_admin --- - -CREATE TYPE dhcpd_dynamic_hosts AS ( - hostname character varying(63), - zone text, - mac macaddr, - owner text, - class text -); - - -ALTER TYPE dhcp.dhcpd_dynamic_hosts OWNER TO starrs_admin; - --- --- Name: dhcpd_global_options; Type: TYPE; Schema: dhcp; Owner: starrs_admin --- - -CREATE TYPE dhcpd_global_options AS ( - option text, - value text -); - - -ALTER TYPE dhcp.dhcpd_global_options OWNER TO starrs_admin; - --- --- Name: TYPE dhcpd_global_options; Type: COMMENT; Schema: dhcp; Owner: starrs_admin --- - -COMMENT ON TYPE dhcpd_global_options IS 'Get all global DHCPD config directives'; - - --- --- Name: dhcpd_keys; Type: TYPE; Schema: dhcp; Owner: starrs_admin --- - -CREATE TYPE dhcpd_keys AS ( - keyname text, - key text -); - - -ALTER TYPE dhcp.dhcpd_keys OWNER TO starrs_admin; - --- --- Name: TYPE dhcpd_keys; Type: COMMENT; Schema: dhcp; Owner: starrs_admin --- - -COMMENT ON TYPE dhcpd_keys IS 'get the keys of the DHCP enabled subnet zones'; - - --- --- Name: dhcpd_range_options; Type: TYPE; Schema: dhcp; Owner: starrs_admin --- - -CREATE TYPE dhcpd_range_options AS ( - option text, - value text -); - - -ALTER TYPE dhcp.dhcpd_range_options OWNER TO starrs_admin; - --- --- Name: TYPE dhcpd_range_options; Type: COMMENT; Schema: dhcp; Owner: starrs_admin --- - -COMMENT ON TYPE dhcpd_range_options IS 'range options for the dhcpd.conf'; - - --- --- Name: dhcpd_range_settings; Type: TYPE; Schema: dhcp; Owner: starrs_admin --- - -CREATE TYPE dhcpd_range_settings AS ( - setting text, - value text -); - - -ALTER TYPE dhcp.dhcpd_range_settings OWNER TO starrs_admin; - --- --- Name: TYPE dhcpd_range_settings; Type: COMMENT; Schema: dhcp; Owner: starrs_admin --- - -COMMENT ON TYPE dhcpd_range_settings IS 'range settings for the dhcpd.conf'; - - --- --- Name: dhcpd_static_hosts; Type: TYPE; Schema: dhcp; Owner: starrs_admin --- - -CREATE TYPE dhcpd_static_hosts AS ( - hostname character varying(63), - zone text, - mac macaddr, - address inet, - owner text, - class text -); - - -ALTER TYPE dhcp.dhcpd_static_hosts OWNER TO starrs_admin; - --- --- Name: TYPE dhcpd_static_hosts; Type: COMMENT; Schema: dhcp; Owner: starrs_admin --- - -COMMENT ON TYPE dhcpd_static_hosts IS 'Dynamic host information for the dhcpd.conf'; - - --- --- Name: dhcpd_subnet_options; Type: TYPE; Schema: dhcp; Owner: starrs_admin --- - -CREATE TYPE dhcpd_subnet_options AS ( - option text, - value text -); - - -ALTER TYPE dhcp.dhcpd_subnet_options OWNER TO starrs_admin; - --- --- Name: TYPE dhcpd_subnet_options; Type: COMMENT; Schema: dhcp; Owner: starrs_admin --- - -COMMENT ON TYPE dhcpd_subnet_options IS 'Subnet options for the dhcpd.conf'; - - --- --- Name: dhcpd_subnet_ranges; Type: TYPE; Schema: dhcp; Owner: starrs_admin --- - -CREATE TYPE dhcpd_subnet_ranges AS ( - name text, - first_ip inet, - last_ip inet, - class text -); - - -ALTER TYPE dhcp.dhcpd_subnet_ranges OWNER TO starrs_admin; - --- --- Name: TYPE dhcpd_subnet_ranges; Type: COMMENT; Schema: dhcp; Owner: starrs_admin --- - -COMMENT ON TYPE dhcpd_subnet_ranges IS 'list all dynamic ranges within a subnet'; - - --- --- Name: dhcpd_subnet_settings; Type: TYPE; Schema: dhcp; Owner: starrs_admin --- - -CREATE TYPE dhcpd_subnet_settings AS ( - setting text, - value text -); - - -ALTER TYPE dhcp.dhcpd_subnet_settings OWNER TO starrs_admin; - --- --- Name: TYPE dhcpd_subnet_settings; Type: COMMENT; Schema: dhcp; Owner: starrs_admin --- - -COMMENT ON TYPE dhcpd_subnet_settings IS 'Subnet settings for the dhcpd.conf'; - - --- --- Name: dhcpd_zones; Type: TYPE; Schema: dhcp; Owner: starrs_admin --- - -CREATE TYPE dhcpd_zones AS ( - zone text, - keyname text, - primary_ns inet -); - - -ALTER TYPE dhcp.dhcpd_zones OWNER TO starrs_admin; - --- --- Name: TYPE dhcpd_zones; Type: COMMENT; Schema: dhcp; Owner: starrs_admin --- - -COMMENT ON TYPE dhcpd_zones IS 'Zone information for dhcpd'; - - -SET search_path = dns, pg_catalog; - --- --- Name: zone_audit_data; Type: TYPE; Schema: dns; Owner: starrs_admin --- - -CREATE TYPE zone_audit_data AS ( - host text, - ttl integer, - type text, - address inet, - port integer, - weight integer, - priority integer, - preference integer, - target text, - text text, - contact text, - serial text, - refresh integer, - retry integer, - expire integer, - minimum integer -); - - -ALTER TYPE dns.zone_audit_data OWNER TO starrs_admin; - --- --- Name: TYPE zone_audit_data; Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON TYPE zone_audit_data IS 'All DNS zone data for auditing purposes'; - - -SET search_path = libvirt, pg_catalog; - --- --- Name: domain_data; Type: TYPE; Schema: libvirt; Owner: starrs_admin --- - -CREATE TYPE domain_data AS ( - domain text, - state text, - definition text -); - - -ALTER TYPE libvirt.domain_data OWNER TO starrs_admin; - --- --- Name: domains; Type: TYPE; Schema: libvirt; Owner: starrs_admin --- - -CREATE TYPE domains AS ( - host_name text, - domain_name text, - state text, - definition text, - date_created timestamp without time zone, - date_modified timestamp without time zone, - last_modifier text -); - - -ALTER TYPE libvirt.domains OWNER TO starrs_admin; - -SET search_path = management, pg_catalog; - --- --- Name: search_data; Type: TYPE; Schema: management; Owner: starrs_admin --- - -CREATE TYPE search_data AS ( - datacenter text, - availability_zone text, - system_name text, - location text, - asset text, - "group" text, - platform text, - mac macaddr, - address inet, - config text, - system_owner text, - system_last_modifier text, - range text, - hostname character varying(63), - cname_alias character varying(63), - srv_alias character varying(63), - zone text, - dns_owner text, - dns_last_modifier text -); - - -ALTER TYPE management.search_data OWNER TO starrs_admin; - -SET search_path = network, pg_catalog; - --- --- Name: cam; Type: TYPE; Schema: network; Owner: starrs_admin --- - -CREATE TYPE cam AS ( - mac macaddr, - ifindex integer, - vlan integer -); - - -ALTER TYPE network.cam OWNER TO starrs_admin; - --- --- Name: switchports; Type: TYPE; Schema: network; Owner: starrs_admin --- - -CREATE TYPE switchports AS ( - system_name text, - name text, - "desc" text, - ifindex integer, - alias text, - admin_state boolean, - oper_state boolean, - date_created timestamp without time zone, - date_modified timestamp without time zone, - last_modifier text, - vlan integer -); - - -ALTER TYPE network.switchports OWNER TO starrs_admin; - -SET search_path = systems, pg_catalog; - --- --- Name: os_distribution; Type: TYPE; Schema: systems; Owner: starrs_admin --- - -CREATE TYPE os_distribution AS ( - name text, - count integer, - percentage integer -); - - -ALTER TYPE systems.os_distribution OWNER TO starrs_admin; - --- --- Name: TYPE os_distribution; Type: COMMENT; Schema: systems; Owner: starrs_admin --- - -COMMENT ON TYPE os_distribution IS 'OS distribution statistics'; - - --- --- Name: os_family_distribution; Type: TYPE; Schema: systems; Owner: starrs_admin --- - -CREATE TYPE os_family_distribution AS ( - family text, - count integer, - percentage integer -); - - -ALTER TYPE systems.os_family_distribution OWNER TO starrs_admin; - --- --- Name: TYPE os_family_distribution; Type: COMMENT; Schema: systems; Owner: starrs_admin --- - -COMMENT ON TYPE os_family_distribution IS 'OS distribution statistics'; - - -SET search_path = api, pg_catalog; - --- --- Name: add_libvirt_domain(text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION add_libvirt_domain(input_host text, input_domain text) RETURNS SETOF libvirt.domains - LANGUAGE plpgsql - AS $$ - BEGIN - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF (SELECT "owner" FROM "system"."systems" WHERE "system_name" = input_host) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied: Not owner of host!'; - END IF; - - IF (SELECT "owner" FROM "system"."systems" WHERE "system_name" = input_domain) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied: Not owner of domain!'; - END IF; - END IF; - - IF (SELECT "type" FROM "systems"."systems" WHERE "system_name" = input_host) != 'VM Host' THEN - RAISE EXCEPTION 'Host type mismatch. You need a VM Host.'; - END IF; - - IF (SELECT "type" FROM "systems"."systems" WHERE "system_name" = input_domain) != 'Virtual Machine' THEN - RAISE EXCEPTION 'Domain type mismatch. You need a Virtual Machine.'; - END IF; - - INSERT INTO "libvirt"."domains" ("host_name", "domain_name") VALUES (input_host, input_domain); - - RETURN QUERY (SELECT * FROM "libvirt"."domains" WHERE "domain_name" = input_domain); - END; -$$; - - -ALTER FUNCTION api.add_libvirt_domain(input_host text, input_domain text) OWNER TO starrs_admin; - --- --- Name: FUNCTION add_libvirt_domain(input_host text, input_domain text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION add_libvirt_domain(input_host text, input_domain text) IS 'Assign a VM to a host'; - - --- --- Name: change_username(text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION change_username(old_username text, new_username text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Only admins can change usernames'; - END IF; - - -- Perform update - UPDATE "dhcp"."class_options" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "ip"."range_uses" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "ip"."subnets" SET "owner" = new_username WHERE "owner" = old_username; - UPDATE "ip"."subnets" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "ip"."ranges" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "dns"."ns" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "systems"."os_family" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "systems"."interface_addresses" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "dhcp"."classes" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "systems"."systems" SET "owner" = new_username WHERE "owner" = old_username; - UPDATE "systems"."systems" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "dhcp"."subnet_options" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "dhcp"."config_types" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "systems"."os" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "dns"."cname" SET "owner" = new_username WHERE "owner" = old_username; - UPDATE "dns"."cname" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "dns"."srv" SET "owner" = new_username WHERE "owner" = old_username; - UPDATE "dns"."srv" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "dns"."mx" SET "owner" = new_username WHERE "owner" = old_username; - UPDATE "dns"."mx" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "dns"."zones" SET "owner" = new_username WHERE "owner" = old_username; - UPDATE "dns"."zones" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "dns"."soa" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "dns"."keys" SET "owner" = new_username WHERE "owner" = old_username; - UPDATE "dns"."keys" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "ip"."addresses" SET "owner" = new_username WHERE "owner" = old_username; - UPDATE "ip"."addresses" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "dns"."txt" SET "owner" = new_username WHERE "owner" = old_username; - UPDATE "dns"."txt" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "dns"."zone_txt" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "management"."log_master" SET "user" = new_username WHERE "user" = old_username; - UPDATE "dns"."a" SET "owner" = new_username WHERE "owner" = old_username; - UPDATE "dns"."a" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "systems"."interfaces" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "management"."configuration" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "dhcp"."range_options" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "dhcp"."global_options" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "dns"."types" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "dns"."zone_a" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "network"."snmp" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "systems"."architectures" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "systems"."platforms" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "systems"."datacenters" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "systems"."availability_zones" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "management"."group_members" SET "user" = new_username WHERE "user" = old_username; - UPDATE "management"."groups" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "management"."group_members" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "network"."cam_cache" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - UPDATE "network"."vlans" SET "last_modifier" = new_username WHERE "last_modifier" = old_username; - PERFORM api.syslog('changed user "'||old_username||'" to "'||new_username); - - -- Done - END; -$$; - - -ALTER FUNCTION api.change_username(old_username text, new_username text) OWNER TO starrs_admin; - --- --- Name: FUNCTION change_username(old_username text, new_username text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION change_username(old_username text, new_username text) IS 'Change all references to an old username to a new one'; - - --- --- Name: check_dns_hostname(text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION check_dns_hostname(input_hostname text, input_zone text) RETURNS boolean - LANGUAGE plpgsql - AS $$ - DECLARE - RowCount INTEGER := 0; - BEGIN - RowCount := RowCount + (SELECT COUNT(*) FROM "dns"."a" WHERE "hostname" = input_hostname AND "zone" = input_zone); - RowCount := RowCount + (SELECT COUNT(*) FROM "dns"."srv" WHERE "alias" = input_hostname AND "zone" = input_zone); - RowCount := RowCount + (SELECT COUNT(*) FROM "dns"."cname" WHERE "alias" = input_hostname AND "zone" = input_zone); - - IF RowCount = 0 THEN - RETURN FALSE; - ELSE - RETURN TRUE; - END IF; - END; -$$; - - -ALTER FUNCTION api.check_dns_hostname(input_hostname text, input_zone text) OWNER TO starrs_admin; - --- --- Name: FUNCTION check_dns_hostname(input_hostname text, input_zone text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION check_dns_hostname(input_hostname text, input_zone text) IS 'Check if a hostname is available in a given zone'; - - --- --- Name: clear_expired_addresses(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION clear_expired_addresses() RETURNS void - LANGUAGE plpgsql - AS $$ - DECLARE - SystemData RECORD; - BEGIN - --FOR SystemData IN (SELECT "system_name" FROM "systems"."systems" WHERE "systems"."systems"."renew_date" = current_date) LOOP - -- PERFORM "api"."remove_system"(SystemData.system_name); - --END LOOP; - FOR SystemData IN (SELECT "address" FROM "systems"."interface_addresses" WHERE "renew_date" <= current_date) LOOP - PERFORM "api"."remove_interface_address"(SystemData.address); - END LOOP; - END; -$$; - - -ALTER FUNCTION api.clear_expired_addresses() OWNER TO starrs_admin; - --- --- Name: FUNCTION clear_expired_addresses(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION clear_expired_addresses() IS 'Remove all expired addresses.'; - - --- --- Name: control_libvirt_domain(text, text, text, text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION control_libvirt_domain(sysuri text, syspassword text, domain text, action text) RETURNS text - LANGUAGE plpython2u - AS $$ - #!/usr/bin/python - - import libvirt - import sys - - def request_credentials(credentials, data): - for credential in credentials: - if credential[0] == libvirt.VIR_CRED_AUTHNAME: - return 0 - elif credential[0] == libvirt.VIR_CRED_NOECHOPROMPT: - credential[4] = syspassword - else: - return -1 - - return 0 - - auth = [[libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_NOECHOPROMPT], request_credentials, None] - conn = libvirt.openAuth(sysuri, auth, 0) - - dom = conn.lookupByName(domain) - - if action == 'destroy': - dom.destroy() - elif action == 'shutdown': - dom.shutdown() - elif action == 'reboot': - dom.reboot(0) - elif action == 'reset': - dom.reset(0) - elif action == 'resume': - dom.resume() - elif action == 'restore': - dom.restore() - elif action == 'suspend': - dom.suspend() - elif action == 'save': - dom.save() - elif action == 'create': - dom.create() - else: - sys.exit("Invalid action") - - conn.close() - state_names = { libvirt.VIR_DOMAIN_RUNNING : "running", - libvirt.VIR_DOMAIN_BLOCKED : "idle", - libvirt.VIR_DOMAIN_PAUSED : "paused", - libvirt.VIR_DOMAIN_SHUTDOWN : "in shutdown", - libvirt.VIR_DOMAIN_SHUTOFF : "shut off", - libvirt.VIR_DOMAIN_CRASHED : "crashed", - libvirt.VIR_DOMAIN_NOSTATE : "no state" } - return state_names[dom.info()[0]] -$$; - - -ALTER FUNCTION api.control_libvirt_domain(sysuri text, syspassword text, domain text, action text) OWNER TO postgres; - --- --- Name: create_address_range(inet, inet, cidr); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_address_range(input_first_ip inet, input_last_ip inet, input_subnet cidr) RETURNS void - LANGUAGE plpgsql - AS $$ - DECLARE - RowCount INTEGER; - Owner TEXT; - RangeAddresses RECORD; - BEGIN - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "ip"."subnets" WHERE "subnet" = input_subnet) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied on subnet %. You are not owner',input_subnet; - END IF; - END IF; - - -- Check if subnet exists - SELECT COUNT(*) INTO RowCount - FROM "ip"."subnets" - WHERE "ip"."subnets"."subnet" = input_subnet; - IF (RowCount < 1) THEN - RAISE EXCEPTION 'Subnet (%) does not exist.',input_subnet; - END IF; - - -- Check if addresses are within subnet - IF NOT input_first_ip << input_subnet THEN - RAISE EXCEPTION 'First address (%) not within subnet (%)',input_first_ip,input_subnet; - END IF; - - IF NOT input_last_ip << input_subnet THEN - RAISE EXCEPTION 'Last address (%) not within subnet (%)',input_last_ip,input_subnet; - END IF; - - -- Check if autogen'd - IF (SELECT "autogen" FROM "ip"."subnets" WHERE "ip"."subnets"."subnet" = input_subnet LIMIT 1) IS TRUE THEN - RAISE EXCEPTION 'Subnet (%) addresses were autogenerated. Cannot create new addresses.',input_subnet; - END IF; - - -- Get owner - SELECT "ip"."subnets"."owner" INTO Owner - FROM "ip"."subnets" - WHERE "ip"."subnets"."subnet" = input_subnet; - - -- Create addresses - FOR RangeAddresses IN SELECT api.get_range_addresses(input_first_ip,input_last_ip) LOOP - INSERT INTO "ip"."addresses" ("address","owner") VALUES (RangeAddresses.get_range_addresses,Owner); - END LOOP; - - -- Done - PERFORM api.syslog('create_address_range:"'||input_first_ip||'","'||input_last_ip||'","'||input_subnet||'"'); - PERFORM api.syslog('WARNING! Potential deprecated function in use!'); - END; -$$; - - -ALTER FUNCTION api.create_address_range(input_first_ip inet, input_last_ip inet, input_subnet cidr) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_address_range(input_first_ip inet, input_last_ip inet, input_subnet cidr); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_address_range(input_first_ip inet, input_last_ip inet, input_subnet cidr) IS 'Create a range of addresses from a non-autogened subnet (intended for DHCPv6)'; - - --- --- Name: get_current_user(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_current_user() RETURNS text - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN (SELECT "username" - FROM "user_privileges" - WHERE "privilege" = 'USERNAME'); - END; -$$; - - -ALTER FUNCTION api.get_current_user() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_current_user(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_current_user() IS 'Get the username of the current session'; - - -SET search_path = systems, pg_catalog; - -SET default_tablespace = ''; - -SET default_with_oids = false; - --- --- Name: availability_zones; Type: TABLE; Schema: systems; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE availability_zones ( - datacenter text NOT NULL, - zone text NOT NULL, - comment text, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE systems.availability_zones OWNER TO starrs_admin; - --- --- Name: TABLE availability_zones; Type: COMMENT; Schema: systems; Owner: starrs_admin --- - -COMMENT ON TABLE availability_zones IS 'Availability zones within datacenters'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_availability_zone(text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_availability_zone(input_datacenter text, input_zone text, input_comment text) RETURNS SETOF systems.availability_zones - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission denied to create availability zone: not admin'; - END IF; - - -- Create availability_zones - INSERT INTO "systems"."availability_zones" ("datacenter","zone","comment") VALUES (input_datacenter, input_zone, input_comment); - - -- Done - PERFORM api.syslog('create_availability_zone:"'||input_datacenter||'","'||input_zone||'"'); - RETURN QUERY (SELECT * FROM "systems"."availability_zones" WHERE "datacenter" = input_datacenter AND "zone" = input_zone); - END; -$$; - - -ALTER FUNCTION api.create_availability_zone(input_datacenter text, input_zone text, input_comment text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_availability_zone(input_datacenter text, input_zone text, input_comment text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_availability_zone(input_datacenter text, input_zone text, input_comment text) IS 'Create a new availability zone'; - - -SET search_path = systems, pg_catalog; - --- --- Name: datacenters; Type: TABLE; Schema: systems; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE datacenters ( - datacenter text NOT NULL, - comment text, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE systems.datacenters OWNER TO starrs_admin; - --- --- Name: TABLE datacenters; Type: COMMENT; Schema: systems; Owner: starrs_admin --- - -COMMENT ON TABLE datacenters IS 'Regional locations for systems'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_datacenter(text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_datacenter(input_name text, input_comment text) RETURNS SETOF systems.datacenters - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission denied to create datacenter: not admin'; - END IF; - - -- Create datacenter - INSERT INTO "systems"."datacenters" ("datacenter","comment") VALUES (input_name,input_comment); - - -- Done - PERFORM api.syslog('create_datacenter:"'||input_name||'"'); - RETURN QUERY (SELECT * FROM "systems"."datacenters" WHERE "datacenter" = input_name); - END; -$$; - - -ALTER FUNCTION api.create_datacenter(input_name text, input_comment text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_datacenter(input_name text, input_comment text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_datacenter(input_name text, input_comment text) IS 'Create a new datacenter'; - - -SET search_path = dhcp, pg_catalog; - --- --- Name: classes; Type: TABLE; Schema: dhcp; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE classes ( - class text NOT NULL, - comment text, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE dhcp.classes OWNER TO starrs_admin; - --- --- Name: TABLE classes; Type: COMMENT; Schema: dhcp; Owner: starrs_admin --- - -COMMENT ON TABLE classes IS 'DHCP classes allow configuration of hosts in certain ways'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_dhcp_class(text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_dhcp_class(input_class text, input_comment text) RETURNS SETOF dhcp.classes - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - RAISE EXCEPTION 'Permission to create dhcp class denied for %. Not admin.',api.get_current_user(); - END IF; - - -- Validate input - input_class := api.validate_nospecial(input_class); - - -- Create new class - INSERT INTO "dhcp"."classes" ("class","comment") VALUES (input_class,input_comment); - - -- Done - PERFORM api.syslog('create_dhcp_class:"'||input_class||'"'); - RETURN QUERY (SELECT * FROM "dhcp"."classes" WHERE "class" = input_class); - END; -$$; - - -ALTER FUNCTION api.create_dhcp_class(input_class text, input_comment text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_dhcp_class(input_class text, input_comment text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_dhcp_class(input_class text, input_comment text) IS 'Create a new DHCP class'; - - -SET search_path = dhcp, pg_catalog; - --- --- Name: class_options; Type: TABLE; Schema: dhcp; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE class_options ( - option text NOT NULL, - value text NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL, - class text NOT NULL -); - - -ALTER TABLE dhcp.class_options OWNER TO starrs_admin; - --- --- Name: TABLE class_options; Type: COMMENT; Schema: dhcp; Owner: starrs_admin --- - -COMMENT ON TABLE class_options IS 'Options to apply to a specific DHCP class (like Netbooting)'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_dhcp_class_option(text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_dhcp_class_option(input_class text, input_option text, input_value text) RETURNS SETOF dhcp.class_options - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - RAISE EXCEPTION 'Permission to create dhcp class option denied for %. Not admin.',api.get_current_user(); - END IF; - - -- Create class option - INSERT INTO "dhcp"."class_options" - ("class","option","value") VALUES - (input_class,input_option,input_value); - - -- Done - PERFORM api.syslog('create_dhcp_class_option:"'||input_class||'","'||input_option||'","'||input_value||'"'); - RETURN QUERY (SELECT * FROM "dhcp"."class_options" WHERE "class" = input_class AND "option" = input_option AND "value" = input_value); - END; -$$; - - -ALTER FUNCTION api.create_dhcp_class_option(input_class text, input_option text, input_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_dhcp_class_option(input_class text, input_option text, input_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_dhcp_class_option(input_class text, input_option text, input_value text) IS 'Create a new DHCP class option'; - - -SET search_path = dhcp, pg_catalog; - --- --- Name: global_options; Type: TABLE; Schema: dhcp; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE global_options ( - option text NOT NULL, - value text NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE dhcp.global_options OWNER TO starrs_admin; - --- --- Name: TABLE global_options; Type: COMMENT; Schema: dhcp; Owner: starrs_admin --- - -COMMENT ON TABLE global_options IS 'Global DHCP options that affect all objects'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_dhcp_global_option(text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_dhcp_global_option(input_option text, input_value text) RETURNS SETOF dhcp.global_options - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - RAISE EXCEPTION 'Permission to create dhcp class option denied for %. Not admin.',api.get_current_user(); - END IF; - - -- Create class option - INSERT INTO "dhcp"."global_options" - ("option","value") VALUES (input_option,input_value); - - -- Done - PERFORM api.syslog('create_dhcp_global_option:"'||input_option||'","'||input_value||'"'); - RETURN QUERY (SELECT * FROM "dhcp"."global_options" WHERE "option" = input_option AND "value" = input_value); - END; -$$; - - -ALTER FUNCTION api.create_dhcp_global_option(input_option text, input_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_dhcp_global_option(input_option text, input_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_dhcp_global_option(input_option text, input_value text) IS 'Create a new DHCP global option'; - - -SET search_path = dhcp, pg_catalog; - --- --- Name: range_options; Type: TABLE; Schema: dhcp; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE range_options ( - option text NOT NULL, - name text NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL, - value text NOT NULL -); - - -ALTER TABLE dhcp.range_options OWNER TO starrs_admin; - --- --- Name: TABLE range_options; Type: COMMENT; Schema: dhcp; Owner: starrs_admin --- - -COMMENT ON TABLE range_options IS 'DHCP options that apply to a specific range'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_dhcp_range_option(text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_dhcp_range_option(input_range text, input_option text, input_value text) RETURNS SETOF dhcp.range_options - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission to create dhcp range option denied for user %. You are not admin.',api.get_current_user(); - END IF; - - -- Check if range is marked for DHCP - IF (SELECT "use" FROM "ip"."ranges" WHERE "name" = input_range) !~* 'ROAM' THEN - RAISE EXCEPTION 'Range % is not marked for DHCP configuration',input_range; - END IF; - - -- Create option - INSERT INTO "dhcp"."range_options" ("name","option","value","last_modifier") - VALUES (input_range, input_option, input_value, api.get_current_user()); - - -- Done - PERFORM api.syslog('create_dhcp_range_option:"'||input_range||'","'||input_option||'","'||input_value||'"'); - RETURN QUERY (SELECT * FROM "dhcp"."range_options" WHERE "name" = input_range AND "option" = input_option AND "value" = input_value); - END; -$$; - - -ALTER FUNCTION api.create_dhcp_range_option(input_range text, input_option text, input_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_dhcp_range_option(input_range text, input_option text, input_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_dhcp_range_option(input_range text, input_option text, input_value text) IS 'Create a DHCP range option'; - - -SET search_path = dhcp, pg_catalog; - --- --- Name: subnet_options; Type: TABLE; Schema: dhcp; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE subnet_options ( - option text NOT NULL, - value text NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL, - subnet cidr NOT NULL -); - - -ALTER TABLE dhcp.subnet_options OWNER TO starrs_admin; - --- --- Name: TABLE subnet_options; Type: COMMENT; Schema: dhcp; Owner: starrs_admin --- - -COMMENT ON TABLE subnet_options IS 'Options to apply to an entire subnet'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_dhcp_subnet_option(cidr, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_dhcp_subnet_option(input_subnet cidr, input_option text, input_value text) RETURNS SETOF dhcp.subnet_options - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - RAISE EXCEPTION 'Permission to create dhcp subnet option denied for %. Not admin.',api.get_current_user(); - END IF; - - -- Create subnet option - INSERT INTO "dhcp"."subnet_options" - ("subnet","option","value") VALUES - (input_subnet,input_option,input_value); - - -- Done - PERFORM api.syslog('create_dhcp_subnet_option:"'||input_subnet||'","'||input_option||'","'||input_value||'"'); - RETURN QUERY (SELECT * FROM "dhcp"."subnet_options" WHERE "subnet" = input_subnet AND "option" = input_option AND "value" = input_value); - END; -$$; - - -ALTER FUNCTION api.create_dhcp_subnet_option(input_subnet cidr, input_option text, input_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_dhcp_subnet_option(input_subnet cidr, input_option text, input_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_dhcp_subnet_option(input_subnet cidr, input_option text, input_value text) IS 'Create DHCP subnet option'; - - --- --- Name: get_site_configuration(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_site_configuration(input_directive text) RETURNS text - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN (SELECT "value" FROM "management"."configuration" WHERE "option" = input_directive); - END; -$$; - - -ALTER FUNCTION api.get_site_configuration(input_directive text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_site_configuration(input_directive text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_site_configuration(input_directive text) IS 'Get a site configuration directive'; - - -SET search_path = dns, pg_catalog; - --- --- Name: a; Type: TABLE; Schema: dns; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE a ( - hostname character varying(63) NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL, - address inet NOT NULL, - type text NOT NULL, - ttl integer DEFAULT (api.get_site_configuration('DNS_DEFAULT_TTL'::text))::integer NOT NULL, - owner text NOT NULL, - zone text DEFAULT api.get_site_configuration('DNS_DEFAULT_ZONE'::text) NOT NULL, - reverse boolean DEFAULT true NOT NULL, - CONSTRAINT dns_a_hostname CHECK (((hostname)::text !~ '_'::text)), - CONSTRAINT dns_a_type_check CHECK ((type ~ '^A|AAAA$'::text)) -); - - -ALTER TABLE dns.a OWNER TO starrs_admin; - --- --- Name: TABLE a; Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON TABLE a IS 'DNS forward address records'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_dns_address(inet, text, text, integer, text, boolean, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_dns_address(input_address inet, input_hostname text, input_zone text, input_ttl integer, input_type text, input_reverse boolean, input_owner text) RETURNS SETOF dns.a - LANGUAGE plpgsql - AS $_$ - BEGIN - -- Set owner - IF input_owner IS NULL THEN - input_owner := api.get_current_user(); - END IF; - - -- Set zone - IF input_zone IS NULL THEN - input_zone := api.get_site_configuration('DNS_DEFAULT_ZONE'); - END IF; - - -- Fill TTL - IF input_ttl IS NULL THEN - input_ttl := api.get_site_configuration('DNS_DEFAULT_TTL'); - END IF; - - -- Autofill Type - IF input_type IS NULL THEN - IF family(input_address) = 4 THEN - input_type := 'A'; - ELSEIF family(input_address) = 6 THEN - input_type := 'AAAA'; - END IF; - END IF; - - -- Check type - IF input_type !~* '^A|AAAA$' THEN - RAISE EXCEPTION 'Bad type % given',input_type; - END IF; - - -- Lower - input_hostname := lower(input_hostname); - - -- Validate type - IF family(input_address) = 4 AND input_type !~* '^A$' THEN - RAISE EXCEPTION 'IPv4 Address/Type mismatch'; - ELSEIF family(input_address) = 6 AND input_type !~* '^AAAA$' THEN - RAISE EXCEPTION 'IPv6 Address/Type mismatch'; - END IF; - - -- User can only specify TTL if address is static - IF (SELECT "config" FROM "systems"."interface_addresses" WHERE "address" = input_address) !~* 'static' AND input_ttl != (SELECT "value"::integer/2 AS "ttl" FROM "dhcp"."subnet_options" WHERE "option"='default-lease-time' AND "subnet" >> input_address) THEN - RAISE EXCEPTION 'You can only specify a TTL other than the default if your address is configured statically'; - END IF; - - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - -- Shared zone - IF (SELECT "shared" FROM "dns"."zones" WHERE "zone" = input_zone) IS FALSE THEN - RAISE EXCEPTION 'Zone is not shared and you are not admin'; - END IF; - -- You own the system - IF (SELECT "write" FROM api.get_system_permissions(api.get_interface_address_system(input_address))) IS FALSE THEN - RAISE EXCEPTION 'Permission denied'; - END IF; - -- You specified another owner - IF input_owner != api.get_current_user() THEN - RAISE EXCEPTION 'Only admins can define a different owner (%).',input_owner; - END IF; - END IF; - - -- Validate hostname - IF api.validate_domain(input_hostname,input_zone) IS FALSE THEN - RAISE EXCEPTION 'Invalid hostname (%) and domain (%)',input_hostname,input_zone; - END IF; - - -- Create record - INSERT INTO "dns"."a" ("hostname","zone","address","ttl","type","owner","reverse") VALUES - (input_hostname,input_zone,input_address,input_ttl,input_type,input_owner,input_reverse); - - -- Done - PERFORM api.syslog('create_dns_address:"'||input_address||'","'||input_hostname||'","'||input_zone||'"'); - RETURN QUERY (SELECT * FROM "dns"."a" WHERE "address" = input_address AND "hostname" = input_hostname AND "zone" = input_zone); - END; -$_$; - - -ALTER FUNCTION api.create_dns_address(input_address inet, input_hostname text, input_zone text, input_ttl integer, input_type text, input_reverse boolean, input_owner text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_dns_address(input_address inet, input_hostname text, input_zone text, input_ttl integer, input_type text, input_reverse boolean, input_owner text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_dns_address(input_address inet, input_hostname text, input_zone text, input_ttl integer, input_type text, input_reverse boolean, input_owner text) IS 'create a new A or AAAA record'; - - -SET search_path = dns, pg_catalog; - --- --- Name: cname; Type: TABLE; Schema: dns; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE cname ( - alias character varying(63) NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL, - hostname character varying(63) NOT NULL, - address inet NOT NULL, - ttl integer DEFAULT (api.get_site_configuration('DNS_DEFAULT_TTL'::text))::integer NOT NULL, - owner text NOT NULL, - type text DEFAULT 'CNAME'::text NOT NULL, - zone text DEFAULT api.get_site_configuration('DNS_DEFAULT_ZONE'::text) NOT NULL -); - - -ALTER TABLE dns.cname OWNER TO starrs_admin; - --- --- Name: TABLE cname; Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON TABLE cname IS 'CNAME records'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_dns_cname(text, text, text, integer, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_dns_cname(input_alias text, input_target text, input_zone text, input_ttl integer, input_owner text) RETURNS SETOF dns.cname - LANGUAGE plpgsql - AS $$ - BEGIN - -- Validate input - IF api.validate_domain(input_alias,NULL) IS FALSE THEN - RAISE EXCEPTION 'Invalid alias (%)',input_alias; - END IF; - - -- Set owner - IF input_owner IS NULL THEN - input_owner := api.get_current_user(); - END IF; - - -- Set zone - IF input_zone IS NULL THEN - input_zone := api.get_site_configuration('DNS_DEFAULT_ZONE'); - END IF; - - -- Fill TTL - IF input_ttl IS NULL THEN - input_ttl := api.get_site_configuration('DNS_DEFAULT_TTL'); - END IF; - - -- Lower - input_target := lower(input_target); - input_alias := lower(input_alias); - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - -- You specified another owner - IF input_owner != api.get_current_user() THEN - RAISE EXCEPTION 'Only administrators can define a different owner (%).',input_owner; - END IF; - -- You own the system - IF (SELECT "write" FROM api.get_system_permissions(api.get_interface_address_system((SELECT "address" FROM "dns"."a" WHERE "hostname" = input_target AND "zone" = input_zone)))) IS FALSE THEN - RAISE EXCEPTION 'Permission denied'; - END IF; - END IF; - - -- Check for in use - IF (SELECT api.check_dns_hostname(input_alias, input_zone)) IS TRUE THEN - RAISE EXCEPTION 'Record with this hostname and zone already exists'; - END IF; - - -- Create record - INSERT INTO "dns"."cname" ("alias","hostname","zone","ttl","owner") VALUES - (input_alias, input_target, input_zone, input_ttl, input_owner); - - -- Done - PERFORM api.syslog('create_dns_cname:"'||input_alias||'","'||input_target||'","'||input_zone||'"'); - RETURN QUERY (SELECT * FROM "dns"."cname" WHERE "alias" = input_alias AND "hostname" = input_target AND "zone" = input_zone); - END; -$$; - - -ALTER FUNCTION api.create_dns_cname(input_alias text, input_target text, input_zone text, input_ttl integer, input_owner text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_dns_cname(input_alias text, input_target text, input_zone text, input_ttl integer, input_owner text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_dns_cname(input_alias text, input_target text, input_zone text, input_ttl integer, input_owner text) IS 'create a new dns cname record for a host'; - - -SET search_path = dns, pg_catalog; - --- --- Name: keys; Type: TABLE; Schema: dns; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE keys ( - keyname text NOT NULL, - key text NOT NULL, - enctype text NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL, - comment text, - owner text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE dns.keys OWNER TO starrs_admin; - --- --- Name: TABLE keys; Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON TABLE keys IS 'Zone keys'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_dns_key(text, text, text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_dns_key(input_keyname text, input_key text, input_enctype text, input_owner text, input_comment text) RETURNS SETOF dns.keys - LANGUAGE plpgsql - AS $$ - BEGIN - -- Validate input - input_keyname := api.validate_nospecial(input_keyname); - - -- Fill in owner - IF input_owner IS NULL THEN - input_owner := api.get_current_user(); - END IF; - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF input_owner != api.get_current_user() THEN - RAISE EXCEPTION 'Only administrators can define a different owner (%).',input_owner; - END IF; - END IF; - - -- Create new key - INSERT INTO "dns"."keys" - ("keyname","key","enctype","comment","owner") VALUES - (input_keyname,input_key,input_enctype,input_comment,input_owner); - - -- Done - PERFORM api.syslog('create_dns_key:"'||input_keyname||'"'); - RETURN QUERY (SELECT * FROM "dns"."keys" WHERE "keyname" = input_keyname AND "key" = input_key); - END; -$$; - - -ALTER FUNCTION api.create_dns_key(input_keyname text, input_key text, input_enctype text, input_owner text, input_comment text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_dns_key(input_keyname text, input_key text, input_enctype text, input_owner text, input_comment text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_dns_key(input_keyname text, input_key text, input_enctype text, input_owner text, input_comment text) IS 'Create new DNS key'; - - -SET search_path = dns, pg_catalog; - --- --- Name: mx; Type: TABLE; Schema: dns; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE mx ( - preference integer NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL, - hostname character varying(63) NOT NULL, - address inet NOT NULL, - ttl integer DEFAULT (api.get_site_configuration('DNS_DEFAULT_TTL'::text))::integer NOT NULL, - owner text NOT NULL, - zone text DEFAULT api.get_site_configuration('DNS_DEFAULT_ZONE'::text) NOT NULL, - type text NOT NULL -); - - -ALTER TABLE dns.mx OWNER TO starrs_admin; - --- --- Name: TABLE mx; Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON TABLE mx IS 'Mail servers (MX records)'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_dns_mailserver(text, text, integer, integer, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_dns_mailserver(input_hostname text, input_zone text, input_preference integer, input_ttl integer, input_owner text) RETURNS SETOF dns.mx - LANGUAGE plpgsql - AS $$ - BEGIN - -- Set owner - IF input_owner IS NULL THEN - input_owner := api.get_current_user(); - END IF; - - -- Set zone - IF input_zone IS NULL THEN - input_zone := api.get_site_configuration('DNS_DEFAULT_ZONE'); - END IF; - - -- Fill TTL - IF input_ttl IS NULL THEN - input_ttl := api.get_site_configuration('DNS_DEFAULT_TTL'); - END IF; - - -- Lower - input_hostname := lower(input_hostname); - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - -- You own the zone - IF (SELECT "owner" FROM "dns"."zones" WHERE "zone" = input_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied on zone %. You are not owner.',input_zone; - END IF; - -- You specified a different owner - IF input_owner != api.get_current_user() THEN - RAISE EXCEPTION 'Only administrators can define a different owner (%).',input_owner; - END IF; - END IF; - - -- Create record - INSERT INTO "dns"."mx" ("hostname","zone","preference","ttl","owner","type") VALUES - (input_hostname,input_zone,input_preference,input_ttl,input_owner,'MX'); - - -- Done - PERFORM api.syslog('create_dns_mailserver:"'||input_hostname||'","'||input_zone||'","'||input_preference||'"'); - RETURN QUERY (SELECT * FROM "dns"."mx" WHERE "hostname" = input_hostname AND "zone" = input_zone AND "preference" = input_preference); - END; -$$; - - -ALTER FUNCTION api.create_dns_mailserver(input_hostname text, input_zone text, input_preference integer, input_ttl integer, input_owner text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_dns_mailserver(input_hostname text, input_zone text, input_preference integer, input_ttl integer, input_owner text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_dns_mailserver(input_hostname text, input_zone text, input_preference integer, input_ttl integer, input_owner text) IS 'Create a new mailserver MX record for a zone'; - - -SET search_path = dns, pg_catalog; - --- --- Name: ns; Type: TABLE; Schema: dns; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE ns ( - zone text NOT NULL, - ttl integer DEFAULT (api.get_site_configuration('DNS_DEFAULT_TTL'::text))::integer NOT NULL, - type text DEFAULT 'NS'::text NOT NULL, - nameserver text NOT NULL, - address inet NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE dns.ns OWNER TO starrs_admin; - --- --- Name: TABLE ns; Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON TABLE ns IS 'Nameservers (to be inserted as NS records)'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_dns_ns(text, text, inet, integer); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_dns_ns(input_zone text, input_nameserver text, input_address inet, input_ttl integer) RETURNS SETOF dns.ns - LANGUAGE plpgsql - AS $$ - BEGIN - -- Set zone - IF input_zone IS NULL THEN - input_zone := api.get_site_configuration('DNS_DEFAULT_ZONE'); - END IF; - - -- Fill TTL - IF input_ttl IS NULL THEN - input_ttl := api.get_site_configuration('DNS_DEFAULT_TTL'); - END IF; - - -- Lower - input_nameserver := lower(input_nameserver); - input_zone := lower(input_zone); - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - -- You own the zone - IF (SELECT "owner" FROM "dns"."zones" WHERE "zone" = input_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied on zone %. You are not owner.',input_zone; - END IF; - END IF; - - -- Create record - INSERT INTO "dns"."ns" ("zone","ttl","nameserver","address") VALUES - (input_zone,input_ttl,input_nameserver,input_address); - - -- Update TTLs of other zone records since they all need to be the same - UPDATE "dns"."ns" SET "ttl" = input_ttl WHERE "zone" = input_zone; - - -- Done - PERFORM api.syslog('create_dns_ns:"'||input_nameserver||'"'); - RETURN QUERY (SELECT * FROM "dns"."ns" WHERE "zone" = input_zone AND "nameserver" = input_nameserver); - END; -$$; - - -ALTER FUNCTION api.create_dns_ns(input_zone text, input_nameserver text, input_address inet, input_ttl integer) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_dns_ns(input_zone text, input_nameserver text, input_address inet, input_ttl integer); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_dns_ns(input_zone text, input_nameserver text, input_address inet, input_ttl integer) IS 'create a new NS record for a zone'; - - -SET search_path = dns, pg_catalog; - --- --- Name: soa; Type: TABLE; Schema: dns; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE soa ( - zone text DEFAULT api.get_site_configuration('DNS_DEFAULT_ZONE'::text) NOT NULL, - nameserver text DEFAULT ('ns1.'::text || api.get_site_configuration('DNS_DEFAULT_ZONE'::text)) NOT NULL, - ttl integer DEFAULT (api.get_site_configuration('DNS_DEFAULT_TTL'::text))::integer NOT NULL, - contact text DEFAULT ('hostmaster.'::text || api.get_site_configuration('DNS_DEFAULT_ZONE'::text)) NOT NULL, - serial text DEFAULT '0000000000'::text NOT NULL, - refresh integer DEFAULT 3600 NOT NULL, - retry integer DEFAULT 600 NOT NULL, - expire integer DEFAULT 172800 NOT NULL, - minimum integer DEFAULT 43200 NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE dns.soa OWNER TO starrs_admin; - --- --- Name: TABLE soa; Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON TABLE soa IS 'SOA records for DNS zones'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_dns_soa(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_dns_soa(input_zone text) RETURNS SETOF dns.soa - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "dns"."zones" WHERE "zone" = input_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission to create SOA % denied for user %. Not admin.',input_zone,api.get_current_user(); - END IF; - END IF; - - -- Create soa - INSERT INTO "dns"."soa" SELECT * FROM api.query_dns_soa(input_zone); - - -- Done - PERFORM api.syslog('create_dns_soa:"'||input_zone||'"'); - RETURN QUERY (SELECT * FROM "dns"."soa" WHERE "zone" = input_zone); - END; -$$; - - -ALTER FUNCTION api.create_dns_soa(input_zone text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_dns_soa(input_zone text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_dns_soa(input_zone text) IS 'Create a new DNS soa'; - - -SET search_path = dns, pg_catalog; - --- --- Name: srv; Type: TABLE; Schema: dns; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE srv ( - alias character varying(63) NOT NULL, - priority integer DEFAULT 0 NOT NULL, - weight integer DEFAULT 0 NOT NULL, - port integer NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL, - hostname character varying(63) NOT NULL, - address inet NOT NULL, - ttl integer DEFAULT (api.get_site_configuration('DNS_DEFAULT_TTL'::text))::integer NOT NULL, - owner text NOT NULL, - type text DEFAULT 'SRV'::text NOT NULL, - zone text DEFAULT api.get_site_configuration('DNS_DEFAULT_ZONE'::text) NOT NULL -); - - -ALTER TABLE dns.srv OWNER TO starrs_admin; - --- --- Name: TABLE srv; Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON TABLE srv IS 'SRV records'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_dns_srv(text, text, text, integer, integer, integer, integer, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_dns_srv(input_alias text, input_target text, input_zone text, input_priority integer, input_weight integer, input_port integer, input_ttl integer, input_owner text) RETURNS SETOF dns.srv - LANGUAGE plpgsql - AS $$ - BEGIN - -- Validate input - IF api.validate_srv(input_alias) IS FALSE THEN - RAISE EXCEPTION 'Invalid alias (%)',input_alias; - END IF; - - -- Set owner - IF input_owner IS NULL THEN - input_owner := api.get_current_user(); - END IF; - - -- Set zone - IF input_zone IS NULL THEN - input_zone := api.get_site_configuration('DNS_DEFAULT_ZONE'); - END IF; - - -- Fill TTL - IF input_ttl IS NULL THEN - input_ttl := api.get_site_configuration('DNS_DEFAULT_TTL'); - END IF; - - -- Lower - input_target := lower(input_target); - input_alias := lower(input_alias); - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - -- You own the zone - IF (SELECT "owner" FROM "dns"."zones" WHERE "zone" = input_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied on zone %. You are not owner.',input_zone; - END IF; - -- You specified another owner - IF input_owner != api.get_current_user() THEN - RAISE EXCEPTION 'Only administrators can define a different owner (%).',input_owner; - END IF; - END IF; - - -- Create record - INSERT INTO "dns"."srv" ("alias","hostname","zone","priority","weight","port","ttl","owner") VALUES - (input_alias, input_target, input_zone, input_priority, input_weight, input_port, input_ttl, input_owner); - - -- Done - PERFORM api.syslog('create_dns_srv:"'||input_alias||'","'||input_target||'","'||input_zone||'","'||input_priority||'","'||input_weight||'","'||input_port||'","'||input_ttl||'"'); - RETURN QUERY (SELECT * FROM "dns"."srv" WHERE "alias" = input_alias AND "hostname" = input_target AND "zone" = input_zone AND "priority" = input_priority AND "weight" = input_weight AND "port" = input_port); - END; -$$; - - -ALTER FUNCTION api.create_dns_srv(input_alias text, input_target text, input_zone text, input_priority integer, input_weight integer, input_port integer, input_ttl integer, input_owner text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_dns_srv(input_alias text, input_target text, input_zone text, input_priority integer, input_weight integer, input_port integer, input_ttl integer, input_owner text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_dns_srv(input_alias text, input_target text, input_zone text, input_priority integer, input_weight integer, input_port integer, input_ttl integer, input_owner text) IS 'create a new dns srv record for a zone'; - - -SET search_path = dns, pg_catalog; - --- --- Name: txt; Type: TABLE; Schema: dns; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE txt ( - text text NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL, - hostname character varying(63) NOT NULL, - address inet NOT NULL, - type text DEFAULT 'TXT'::text NOT NULL, - ttl integer DEFAULT (api.get_site_configuration('DNS_DEFAULT_TTL'::text))::integer NOT NULL, - owner text NOT NULL, - zone text DEFAULT api.get_site_configuration('DNS_DEFAULT_ZONE'::text) NOT NULL, - CONSTRAINT dns_txt_type_check CHECK ((type ~* '^TXT$'::text)) -); - - -ALTER TABLE dns.txt OWNER TO starrs_admin; - --- --- Name: TABLE txt; Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON TABLE txt IS 'TXT records for hosts'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_dns_txt(text, text, text, integer, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_dns_txt(input_hostname text, input_zone text, input_text text, input_ttl integer, input_owner text) RETURNS SETOF dns.txt - LANGUAGE plpgsql - AS $$ - BEGIN - -- Set owner - IF input_owner IS NULL THEN - input_owner := api.get_current_user(); - END IF; - - -- Set zone - IF input_zone IS NULL THEN - input_zone := api.get_site_configuration('DNS_DEFAULT_ZONE'); - END IF; - - -- Fill TTL - IF input_ttl IS NULL THEN - input_ttl := api.get_site_configuration('DNS_DEFAULT_TTL'); - END IF; - - -- Lower - input_hostname := lower(input_hostname); - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - -- You own the zone - IF (SELECT "owner" FROM "dns"."zones" WHERE "zone" = input_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied on zone %. You are not owner.',input_zone; - END IF; - -- You specified a different owner - IF input_owner != api.get_current_user() THEN - RAISE EXCEPTION 'Only administrators can define a different owner (%).',input_owner; - END IF; - END IF; - - -- Create record - INSERT INTO "dns"."txt" ("hostname","zone","text","ttl","owner") VALUES - (input_hostname,input_zone,input_text,input_ttl,input_owner); - - -- Done - PERFORM api.syslog('create_dns_txt:"'||input_hostname||'","'||input_zone||'","'||input_text||'"'); - RETURN QUERY (SELECT * FROM "dns"."txt" WHERE "hostname" = input_hostname AND "zone" = input_zone AND "text" = input_text); - END; -$$; - - -ALTER FUNCTION api.create_dns_txt(input_hostname text, input_zone text, input_text text, input_ttl integer, input_owner text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_dns_txt(input_hostname text, input_zone text, input_text text, input_ttl integer, input_owner text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_dns_txt(input_hostname text, input_zone text, input_text text, input_ttl integer, input_owner text) IS 'create a new dns TXT record for a host'; - - -SET search_path = dns, pg_catalog; - --- --- Name: zones; Type: TABLE; Schema: dns; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE zones ( - zone text DEFAULT api.get_site_configuration('DNS_DEFAULT_ZONE'::text) NOT NULL, - forward boolean NOT NULL, - keyname text NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL, - owner text NOT NULL, - comment text, - shared boolean DEFAULT false NOT NULL, - ddns boolean DEFAULT false NOT NULL -); - - -ALTER TABLE dns.zones OWNER TO starrs_admin; - --- --- Name: TABLE zones; Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON TABLE zones IS 'Authoritative DNS zones'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_dns_zone(text, text, boolean, boolean, text, text, boolean); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_dns_zone(input_zone text, input_keyname text, input_forward boolean, input_shared boolean, input_owner text, input_comment text, input_ddns boolean) RETURNS SETOF dns.zones - LANGUAGE plpgsql - AS $$ - BEGIN - -- Validate input - IF api.validate_domain(NULL,input_zone) IS FALSE THEN - RAISE EXCEPTION 'Invalid domain (%)',input_zone; - END IF; - - -- Fill in owner - IF input_owner IS NULL THEN - input_owner = api.get_current_user(); - END IF; - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - RAISE EXCEPTION 'Permission to create zone % denied for user %. Not admin.',input_zone,api.get_current_user(); - END IF; - - -- Create zone - INSERT INTO "dns"."zones" ("zone","keyname","forward","comment","owner","shared","ddns") VALUES - (input_zone,input_keyname,input_forward,input_comment,input_owner,input_shared,input_ddns); - - -- Done - PERFORM api.syslog('create_dns_zone:"'||input_zone||'"'); - RETURN QUERY (SELECT * FROM "dns"."zones" WHERE "zone" = input_zone); - END; -$$; - - -ALTER FUNCTION api.create_dns_zone(input_zone text, input_keyname text, input_forward boolean, input_shared boolean, input_owner text, input_comment text, input_ddns boolean) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_dns_zone(input_zone text, input_keyname text, input_forward boolean, input_shared boolean, input_owner text, input_comment text, input_ddns boolean); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_dns_zone(input_zone text, input_keyname text, input_forward boolean, input_shared boolean, input_owner text, input_comment text, input_ddns boolean) IS 'Create a new DNS zone'; - - -SET search_path = dns, pg_catalog; - --- --- Name: zone_a; Type: TABLE; Schema: dns; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE zone_a ( - hostname text, - zone text DEFAULT api.get_site_configuration('DNS_DEFAULT_ZONE'::text) NOT NULL, - type text NOT NULL, - address inet NOT NULL, - ttl integer DEFAULT (api.get_site_configuration('DNS_DEFAULT_TTL'::text))::integer NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL, - CONSTRAINT dns_zone_a_type_check CHECK ((type ~ '^A|AAAA$'::text)) -); - - -ALTER TABLE dns.zone_a OWNER TO starrs_admin; - --- --- Name: TABLE zone_a; Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON TABLE zone_a IS 'Zone address records'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_dns_zone_a(text, inet, integer); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_dns_zone_a(input_zone text, input_address inet, input_ttl integer) RETURNS SETOF dns.zone_a - LANGUAGE plpgsql - AS $$ - BEGIN - -- Set zone - IF input_zone IS NULL THEN - input_zone := api.get_site_configuration('DNS_DEFAULT_ZONE'); - END IF; - - -- Fill TTL - IF input_ttl IS NULL THEN - input_ttl := api.get_site_configuration('DNS_DEFAULT_TTL'); - END IF; - - -- Check dynamic - IF input_address << api.get_site_configuration('DYNAMIC_SUBNET')::cidr THEN - RAISE EXCEPTION 'Zone A cannot be dynamic'; - END IF; - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - -- You own the zone - IF (SELECT "owner" FROM "dns"."zones" WHERE "zone" = input_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'DNS zone % is not shared and you are not owner. Permission denied.',input_zone; - END IF; - END IF; - - -- Create record - INSERT INTO "dns"."zone_a" ("zone","address","ttl") VALUES - (input_zone,input_address,input_ttl); - - -- Done - PERFORM api.syslog('create_dns_zone_a:"'||input_zone||'","'||input_address||'"'); - RETURN QUERY (SELECT * FROM "dns"."zone_a" WHERE "zone" = input_zone AND "address" = input_address); - END; -$$; - - -ALTER FUNCTION api.create_dns_zone_a(input_zone text, input_address inet, input_ttl integer) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_dns_zone_a(input_zone text, input_address inet, input_ttl integer); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_dns_zone_a(input_zone text, input_address inet, input_ttl integer) IS 'create a new zone A or AAAA record'; - - -SET search_path = dns, pg_catalog; - --- --- Name: zone_txt; Type: TABLE; Schema: dns; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE zone_txt ( - text text NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL, - hostname character varying(63), - type text DEFAULT 'TXT'::text NOT NULL, - ttl integer DEFAULT (api.get_site_configuration('DNS_DEFAULT_TTL'::text))::integer NOT NULL, - zone text DEFAULT api.get_site_configuration('DNS_DEFAULT_ZONE'::text) NOT NULL, - address inet DEFAULT '0.0.0.0'::inet -); - - -ALTER TABLE dns.zone_txt OWNER TO starrs_admin; - --- --- Name: TABLE zone_txt; Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON TABLE zone_txt IS 'TXT records for zones'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_dns_zone_txt(text, text, text, integer); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_dns_zone_txt(input_hostname text, input_zone text, input_text text, input_ttl integer) RETURNS SETOF dns.zone_txt - LANGUAGE plpgsql - AS $$ - BEGIN - -- Set zone - IF input_zone IS NULL THEN - input_zone := api.get_site_configuration('DNS_DEFAULT_ZONE'); - END IF; - - -- Fill TTL - IF input_ttl IS NULL THEN - input_ttl := api.get_site_configuration('DNS_DEFAULT_TTL'); - END IF; - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - -- You own the zone - IF (SELECT "owner" FROM "dns"."zones" WHERE "zone" = input_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied on zone %. You are not owner.',input_zone; - END IF; - END IF; - - -- Lower - input_hostname := lower(input_hostname); - - -- Create record - INSERT INTO "dns"."zone_txt" ("hostname","zone","text","ttl") VALUES - (input_hostname,input_zone,input_text,input_ttl); - - -- Update TTLs for other null hostname records since they all need to be the same. - IF input_hostname IS NULL THEN - UPDATE "dns"."zone_txt" SET "ttl" = input_ttl WHERE "hostname" IS NULL AND "zone" = input_zone; - END IF; - - -- Done - IF input_hostname IS NULL THEN - PERFORM api.syslog('create_dns_zone_txt:"'||input_zone||'","'||input_text||'","'||input_ttl); - RETURN QUERY (SELECT * FROM "dns"."zone_txt" WHERE "hostname" IS NULL AND "zone" = input_zone AND "text" = input_text); - ELSE - PERFORM api.syslog('create_dns_zone_txt:"'||input_hostname||'","'||input_zone||'","'||input_text||'","'||input_ttl); - RETURN QUERY (SELECT * FROM "dns"."zone_txt" WHERE "hostname" = input_hostname AND "zone" = input_zone AND "text" = input_text); - END IF; - END; -$$; - - -ALTER FUNCTION api.create_dns_zone_txt(input_hostname text, input_zone text, input_text text, input_ttl integer) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_dns_zone_txt(input_hostname text, input_zone text, input_text text, input_ttl integer); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_dns_zone_txt(input_hostname text, input_zone text, input_text text, input_ttl integer) IS 'create a new dns zone_txt record for a host'; - - -SET search_path = management, pg_catalog; - --- --- Name: groups; Type: TABLE; Schema: management; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE groups ( - "group" text NOT NULL, - comment text, - privilege text DEFAULT 'USER'::text NOT NULL, - renew_interval interval DEFAULT (api.get_site_configuration('DEFAULT_RENEW_INTERVAL'::text))::interval NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL, - CONSTRAINT management_group_privilege_check CHECK ((privilege ~* '^ADMIN|USER|PROGRAM$'::text)) -); - - -ALTER TABLE management.groups OWNER TO starrs_admin; - --- --- Name: TABLE groups; Type: COMMENT; Schema: management; Owner: starrs_admin --- - -COMMENT ON TABLE groups IS 'Groups of users with different privilege levels'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_group(text, text, text, interval); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_group(input_group text, input_privilege text, input_comment text, input_interval interval) RETURNS SETOF management.groups - LANGUAGE plpgsql - AS $$ - BEGIN - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission denied. Only admins can create groups.'; - END IF; - - IF input_interval IS NULL THEN - input_interval := api.get_site_configuration('DEFAULT_RENEW_INTERVAL'); - END IF; - - INSERT INTO "management"."groups" ("group","privilege","comment","renew_interval") - VALUES (input_group, input_privilege, input_comment, input_interval); - - PERFORM api.syslog('create_group:"'||input_group||'","'||input_privilege||'","'||input_interval||'"'); - RETURN QUERY (SELECT * FROM "management"."groups" WHERE "group" = input_group); - END; -$$; - - -ALTER FUNCTION api.create_group(input_group text, input_privilege text, input_comment text, input_interval interval) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_group(input_group text, input_privilege text, input_comment text, input_interval interval); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_group(input_group text, input_privilege text, input_comment text, input_interval interval) IS 'Create a user group'; - - -SET search_path = management, pg_catalog; - --- --- Name: group_members; Type: TABLE; Schema: management; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE group_members ( - "group" text NOT NULL, - "user" text NOT NULL, - privilege text NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL, - CONSTRAINT management_group_member_privilege_check CHECK ((privilege ~* '^ADMIN|USER|PROGRAM$'::text)) -); - - -ALTER TABLE management.group_members OWNER TO starrs_admin; - --- --- Name: TABLE group_members; Type: COMMENT; Schema: management; Owner: starrs_admin --- - -COMMENT ON TABLE group_members IS 'Map usernames to groups'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_group_member(text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_group_member(input_group text, input_user text, input_privilege text) RETURNS SETOF management.group_members - LANGUAGE plpgsql - AS $$ - BEGIN - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF api.get_current_user() NOT IN (SELECT * FROM api.get_group_admins(input_group)) THEN - RAISE EXCEPTION 'Permission denied. Only admins can create groups.'; - END IF; - END IF; - - INSERT INTO "management"."group_members" ("group","user","privilege") - VALUES (input_group, input_user, input_privilege); - - PERFORM api.syslog('create_group_member:"'||input_group||'","'||input_user||'","'||input_privilege||'"'); - RETURN QUERY (SELECT * FROM "management"."group_members" WHERE "group" = input_group AND "user" = input_user); - END; -$$; - - -ALTER FUNCTION api.create_group_member(input_group text, input_user text, input_privilege text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_group_member(input_group text, input_user text, input_privilege text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_group_member(input_group text, input_user text, input_privilege text) IS 'Assign a user to a group'; - - -SET search_path = management, pg_catalog; - --- --- Name: group_settings; Type: TABLE; Schema: management; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE group_settings ( - "group" text NOT NULL, - privilege text DEFAULT 'USER'::text NOT NULL, - provider text NOT NULL, - hostname text, - id text, - username text, - password text, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE management.group_settings OWNER TO starrs_admin; - --- --- Name: TABLE group_settings; Type: COMMENT; Schema: management; Owner: starrs_admin --- - -COMMENT ON TABLE group_settings IS 'Authentication and provider settings for groups'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_group_settings(text, text, text, text, text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_group_settings(input_group text, input_provider text, input_id text, input_hostname text, input_username text, input_password text, input_privilege text) RETURNS SETOF management.group_settings - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission denied. Only admins can create group provider settings'; - END IF; - - -- Check provider - IF input_provider !~* 'local|vcloud|ldap|ad' THEN - RAISE EXCEPTION 'Invalid provider given: %',input_provider; - END IF; - - -- NULLs - IF input_provider ~* 'vcloud|ldap|ad' THEN - IF input_hostname IS NULL THEN - RAISE EXCEPTION 'Need to give a hostname.'; - END IF; - IF input_id IS NULL THEN - RAISE EXCEPTION 'Need to give an ID.'; - END IF; - IF input_username IS NULL THEN - RAISE EXCEPTION 'Need to give a username.'; - END IF; - if input_password IS NULL THEN - RAISE EXCEPTION 'Need to give a password.'; - END IF; - END IF; - - -- Check privilege level - IF input_privilege!~* 'USER|ADMIN' THEN - RAISE EXCEPTION 'Invalid privilege given: %',input_privilege; - END IF; - - INSERT INTO "management"."group_settings" ("group","provider","id","hostname","username","password","privilege") - VALUES (input_group, input_provider, input_id,input_hostname, input_username, input_password, input_privilege); - - --PERFORM api.syslog('create_group_settings:"'||input_group||'","'||input_provider||'","'||input_id||'","'||input_hostname||'","'||input_username||'","'||input_privilege||'"'); - RETURN QUERY (SELECT * FROM "management"."group_settings" WHERE "group" = input_group); - - END; -$$; - - -ALTER FUNCTION api.create_group_settings(input_group text, input_provider text, input_id text, input_hostname text, input_username text, input_password text, input_privilege text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_group_settings(input_group text, input_provider text, input_id text, input_hostname text, input_username text, input_password text, input_privilege text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_group_settings(input_group text, input_provider text, input_id text, input_hostname text, input_username text, input_password text, input_privilege text) IS 'Create authentication settings'; - - -SET search_path = systems, pg_catalog; - --- --- Name: interfaces; Type: TABLE; Schema: systems; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE interfaces ( - mac macaddr NOT NULL, - comment text, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL, - system_name text, - name text NOT NULL -); - - -ALTER TABLE systems.interfaces OWNER TO starrs_admin; - --- --- Name: TABLE interfaces; Type: COMMENT; Schema: systems; Owner: starrs_admin --- - -COMMENT ON TABLE interfaces IS 'Systems have interfaces that connect to the network. This corresponds to your physical hardware.'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_interface(text, macaddr, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_interface(input_system_name text, input_mac macaddr, input_name text, input_comment text) RETURNS SETOF systems.interfaces - LANGUAGE plpgsql - AS $$ - BEGIN - - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF (SELECT "owner" FROM "systems"."systems" WHERE "system_name" = input_system_name) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied on system %. You are not owner.',input_system_name; - END IF; - END IF; - - -- Validate input - input_name := api.validate_name(input_name); - - -- Create interface - INSERT INTO "systems"."interfaces" - ("system_name","mac","comment","last_modifier","name") VALUES - (input_system_name,input_mac,input_comment,api.get_current_user(),input_name); - - -- Done - PERFORM api.syslog('create_interface:"'||input_mac||'"'); - RETURN QUERY (SELECT * FROM "systems"."interfaces" WHERE "mac" = input_mac); - END; -$$; - - -ALTER FUNCTION api.create_interface(input_system_name text, input_mac macaddr, input_name text, input_comment text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_interface(input_system_name text, input_mac macaddr, input_name text, input_comment text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_interface(input_system_name text, input_mac macaddr, input_name text, input_comment text) IS 'Create a new interface on a system'; - - -SET search_path = systems, pg_catalog; - --- --- Name: interface_addresses; Type: TABLE; Schema: systems; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE interface_addresses ( - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - comment text, - address inet NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL, - config text NOT NULL, - family integer NOT NULL, - isprimary boolean NOT NULL, - renew_date date DEFAULT date((('now'::text)::date + (api.get_site_configuration('DEFAULT_RENEW_INTERVAL'::text))::interval)) NOT NULL, - mac macaddr NOT NULL, - class text NOT NULL -); - - -ALTER TABLE systems.interface_addresses OWNER TO starrs_admin; - --- --- Name: TABLE interface_addresses; Type: COMMENT; Schema: systems; Owner: starrs_admin --- - -COMMENT ON TABLE interface_addresses IS 'Interfaces are assigned IP addresses based on certain rules. If DHCP is being used, then a class may be specified.'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_interface_address(macaddr, inet, text, text, boolean, text, date); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_interface_address(input_mac macaddr, input_address inet, input_config text, input_class text, input_isprimary boolean, input_comment text, input_renew_date date) RETURNS SETOF systems.interface_addresses - LANGUAGE plpgsql - AS $$ - BEGIN - -- Renew - IF input_renew_date IS NULL THEN - input_renew_date := api.get_default_renew_date((SELECT "system_name" FROM "systems"."interfaces" WHERE "mac" = input_mac)); - END IF; - - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF (SELECT "owner" FROM "systems"."interfaces" - JOIN "systems"."systems" ON "systems"."systems"."system_name" = "systems"."interfaces"."system_name" - WHERE "systems"."interfaces"."mac" = input_mac) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied on interface %. You are not owner.',input_mac; - END IF; - - IF input_renew_date != api.get_default_renew_date((SELECT "system_name" FROM "systems"."interfaces" WHERE "mac" = input_mac)) THEN - RAISE EXCEPTION 'Only administrators can specify a different renew date'; - END IF; - END IF; - - -- Fill in class - IF input_class IS NULL THEN - input_class = api.get_site_configuration('DHCPD_DEFAULT_CLASS'); - END IF; - - IF input_address << cidr(api.get_site_configuration('DYNAMIC_SUBNET')) AND input_config !~* 'dhcp' THEN - RAISE EXCEPTION 'Specifified address (%) is only for dynamic DHCP addresses',input_address; - END IF; - - IF (SELECT "use" FROM "api"."get_ip_ranges"() WHERE "name" = (SELECT "api"."get_address_range"(input_address))) ~* 'ROAM' THEN - RAISE EXCEPTION 'Specified address (%) is contained within a Dynamic range',input_address; - END IF; - - -- Create address - INSERT INTO "systems"."interface_addresses" ("mac","address","config","class","comment","last_modifier","isprimary","renew_date") VALUES - (input_mac,input_address,input_config,input_class,input_comment,api.get_current_user(),input_isprimary,input_renew_date); - - -- Done - PERFORM api.syslog('create_interface_address:"'||input_address||'"'); - RETURN QUERY (SELECT * FROM "systems"."interface_addresses" WHERE "address" = input_address); - END; -$$; - - -ALTER FUNCTION api.create_interface_address(input_mac macaddr, input_address inet, input_config text, input_class text, input_isprimary boolean, input_comment text, input_renew_date date) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_interface_address(input_mac macaddr, input_address inet, input_config text, input_class text, input_isprimary boolean, input_comment text, input_renew_date date); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_interface_address(input_mac macaddr, input_address inet, input_config text, input_class text, input_isprimary boolean, input_comment text, input_renew_date date) IS 'create a new address on interface from a specified address'; - - -SET search_path = ip, pg_catalog; - --- --- Name: ranges; Type: TABLE; Schema: ip; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE ranges ( - first_ip inet NOT NULL, - last_ip inet NOT NULL, - comment text, - use character varying(4) NOT NULL, - datacenter text DEFAULT api.get_site_configuration('DEFAULT_DATACENTER'::text) NOT NULL, - zone text NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL, - name text NOT NULL, - subnet cidr, - class text -); - - -ALTER TABLE ip.ranges OWNER TO starrs_admin; - --- --- Name: TABLE ranges; Type: COMMENT; Schema: ip; Owner: starrs_admin --- - -COMMENT ON TABLE ranges IS 'Ranges of addresses can be reserved for specific purposes (Autoreg, Dynamics, etc)'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_ip_range(text, inet, inet, cidr, character varying, text, text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_ip_range(input_name text, input_first_ip inet, input_last_ip inet, input_subnet cidr, input_use character varying, input_class text, input_comment text, input_datacenter text, input_zone text) RETURNS SETOF ip.ranges - LANGUAGE plpgsql - AS $$ - BEGIN - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "ip"."subnets" WHERE "subnet" = input_subnet) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied on subnet %. You are not owner',input_subnet; - END IF; - END IF; - - -- Validate input - input_name := api.validate_name(input_name); - - -- Match subnet datacenter - IF (SELECT "datacenter" FROM "ip"."subnets" WHERE "subnet" = input_subnet) != input_datacenter THEN - RAISE EXCEPTION 'Subnet/Datacenter mismatch'; - END IF; - - -- Create new IP range - INSERT INTO "ip"."ranges" ("name", "first_ip", "last_ip", "subnet", "use", "comment", "class", "datacenter", "zone") VALUES - (input_name,input_first_ip,input_last_ip,input_subnet,input_use,input_comment,input_class,input_datacenter,input_zone); - - -- Done - PERFORM api.syslog('create_ip_range:"'||input_name||'"'); - RETURN QUERY (SELECT * FROM "ip"."ranges" WHERE "name" = input_name); - END; -$$; - - -ALTER FUNCTION api.create_ip_range(input_name text, input_first_ip inet, input_last_ip inet, input_subnet cidr, input_use character varying, input_class text, input_comment text, input_datacenter text, input_zone text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_ip_range(input_name text, input_first_ip inet, input_last_ip inet, input_subnet cidr, input_use character varying, input_class text, input_comment text, input_datacenter text, input_zone text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_ip_range(input_name text, input_first_ip inet, input_last_ip inet, input_subnet cidr, input_use character varying, input_class text, input_comment text, input_datacenter text, input_zone text) IS 'Create a new range of IP addresses'; - - -SET search_path = ip, pg_catalog; - --- --- Name: subnets; Type: TABLE; Schema: ip; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE subnets ( - subnet cidr NOT NULL, - comment text, - autogen boolean DEFAULT true NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL, - name text NOT NULL, - owner text NOT NULL, - zone text DEFAULT api.get_site_configuration('DNS_DEFAULT_ZONE'::text), - dhcp_enable boolean DEFAULT false NOT NULL, - datacenter text DEFAULT api.get_site_configuration('DEFAULT_DATACENTER'::text) NOT NULL, - vlan integer NOT NULL -); - - -ALTER TABLE ip.subnets OWNER TO starrs_admin; - --- --- Name: TABLE subnets; Type: COMMENT; Schema: ip; Owner: starrs_admin --- - -COMMENT ON TABLE subnets IS 'Subnets for which this application has control'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_ip_subnet(cidr, text, text, boolean, boolean, text, text, text, integer); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_ip_subnet(input_subnet cidr, input_name text, input_comment text, input_autogen boolean, input_dhcp boolean, input_zone text, input_owner text, input_datacenter text, input_vlan integer) RETURNS SETOF ip.subnets - LANGUAGE plpgsql - AS $$ - DECLARE - RowCount INTEGER; - BEGIN - -- Validate input - input_name := api.validate_name(input_name); - - -- Fill in owner - IF input_owner IS NULL THEN - input_owner := api.get_current_user(); - END IF; - - -- Fill in zone - IF input_zone IS NULL THEN - input_zone := api.get_site_configuration('DNS_DEFAULT_ZONE'); - END IF; - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF input_dhcp IS TRUE THEN - RAISE EXCEPTION 'Permission to create DHCP-enabled subnet % denied for user %',input_subnet,api.get_current_user(); - END IF; - IF input_owner != api.get_current_user() THEN - RAISE EXCEPTION 'Only administrators can define a different owner (%).',input_owner; - END IF; - END IF; - - -- Create new subnet - INSERT INTO "ip"."subnets" - ("subnet","name","comment","autogen","owner","dhcp_enable","zone","datacenter","vlan") VALUES - (input_subnet,input_name,input_comment,input_autogen,input_owner,input_dhcp,input_zone,input_datacenter,input_vlan); - - -- Create RDNS zone - PERFORM api.create_dns_zone(api.get_reverse_domain(input_subnet),(SELECT "keyname" FROM "dns"."zones" WHERE "zone" = input_zone),FALSE,TRUE,input_owner,'Reverse zone for subnet '||text(input_subnet),(SELECT "ddns" FROM "dns"."zones" WHERE "zone" = input_zone)); - - -- Done - PERFORM api.syslog('create_ip_subnet:"'||input_subnet||'"'); - RETURN QUERY (SELECT * FROM "ip"."subnets" WHERE "subnet" = input_subnet); - END; -$$; - - -ALTER FUNCTION api.create_ip_subnet(input_subnet cidr, input_name text, input_comment text, input_autogen boolean, input_dhcp boolean, input_zone text, input_owner text, input_datacenter text, input_vlan integer) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_ip_subnet(input_subnet cidr, input_name text, input_comment text, input_autogen boolean, input_dhcp boolean, input_zone text, input_owner text, input_datacenter text, input_vlan integer); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_ip_subnet(input_subnet cidr, input_name text, input_comment text, input_autogen boolean, input_dhcp boolean, input_zone text, input_owner text, input_datacenter text, input_vlan integer) IS 'Create/activate a new subnet'; - - -SET search_path = libvirt, pg_catalog; - --- --- Name: hosts; Type: TABLE; Schema: libvirt; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE hosts ( - system_name text NOT NULL, - uri text NOT NULL, - password text, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE libvirt.hosts OWNER TO starrs_admin; - --- --- Name: TABLE hosts; Type: COMMENT; Schema: libvirt; Owner: starrs_admin --- - -COMMENT ON TABLE hosts IS 'VM hosts'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_libvirt_host(text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_libvirt_host(input_system text, input_uri text, input_password text) RETURNS SETOF libvirt.hosts - LANGUAGE plpgsql - AS $$ - BEGIN - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Only admins can create VM hosts'; - END IF; - - IF (SELECT "type" FROM "systems"."systems" WHERE "system_name" = input_system) != 'VM Host' THEN - RAISE EXCEPTION 'System type mismatch. You need a VM Host.'; - END IF; - - INSERT INTO "libvirt"."hosts" ("system_name","uri","password") - VALUES (input_system, input_uri, input_password); - - RETURN QUERY (SELECT * FROM "libvirt"."hosts" WHERE "system_name" = input_system); - END; -$$; - - -ALTER FUNCTION api.create_libvirt_host(input_system text, input_uri text, input_password text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_libvirt_host(input_system text, input_uri text, input_password text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_libvirt_host(input_system text, input_uri text, input_password text) IS 'Create libvirt connection settings for a system'; - - -SET search_path = libvirt, pg_catalog; - --- --- Name: platforms; Type: TABLE; Schema: libvirt; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE platforms ( - platform_name text NOT NULL, - definition text NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE libvirt.platforms OWNER TO starrs_admin; - --- --- Name: TABLE platforms; Type: COMMENT; Schema: libvirt; Owner: starrs_admin --- - -COMMENT ON TABLE platforms IS 'Libvirt definitions for VM platforms'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_libvirt_platform(text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_libvirt_platform(input_name text, input_definition text) RETURNS SETOF libvirt.platforms - LANGUAGE plpgsql - AS $$ - BEGIN - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission denied: Not admin!'; - END IF; - - INSERT INTO "libvirt"."platforms" ("platform_name","definition") VALUES (input_name, input_definition); - - RETURN QUERY (SELECT * FROM "libvirt"."platforms" WHERE "platform_name" = input_name); - END; -$$; - - -ALTER FUNCTION api.create_libvirt_platform(input_name text, input_definition text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_libvirt_platform(input_name text, input_definition text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_libvirt_platform(input_name text, input_definition text) IS 'Store a definition of a libvirt platform'; - - -SET search_path = network, pg_catalog; - --- --- Name: snmp; Type: TABLE; Schema: network; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE snmp ( - system_name text NOT NULL, - address inet NOT NULL, - ro_community text, - rw_community text, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE network.snmp OWNER TO starrs_admin; - --- --- Name: TABLE snmp; Type: COMMENT; Schema: network; Owner: starrs_admin --- - -COMMENT ON TABLE snmp IS 'SNMP community settings for network systems'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_network_snmp(text, inet, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_network_snmp(input_system text, input_address inet, input_ro text, input_rw text) RETURNS SETOF network.snmp - LANGUAGE plpgsql - AS $$ - BEGIN - -- Address - IF input_address IS NULL THEN - input_address := api.get_system_primary_address(input_system); - END IF; - - -- Match address against system - IF(api.get_interface_address_system(input_address) != input_system) THEN - RAISE EXCEPTION 'Address % is not a part of the system %',input_address,input_system; - END IF; - - -- Don't allow dynamic IPs - IF input_address << api.get_site_configuration('DYNAMIC_SUBNET')::cidr THEN - RAISE EXCEPTION 'System address cannot be dynamic'; - END IF; - - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF (SELECT "owner" FROM "systems"."systems" WHERE "system_name" = input_system) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied: you are not owner'; - END IF; - END IF; - - -- Create it - INSERT INTO "network"."snmp" ("system_name","address","ro_community","rw_community") - VALUES (input_system, input_address, input_ro, input_rw); - - -- Done - PERFORM api.syslog('create_network_snmp:"'||input_system||'"'); - RETURN QUERY (SELECT * FROM "network"."snmp" WHERE "system_name" = input_system); - END; -$$; - - -ALTER FUNCTION api.create_network_snmp(input_system text, input_address inet, input_ro text, input_rw text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_network_snmp(input_system text, input_address inet, input_ro text, input_rw text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_network_snmp(input_system text, input_address inet, input_ro text, input_rw text) IS 'Create a set of credentials for a system'; - - -SET search_path = systems, pg_catalog; - --- --- Name: platforms; Type: TABLE; Schema: systems; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE platforms ( - platform_name text NOT NULL, - architecture text NOT NULL, - disk text NOT NULL, - cpu text NOT NULL, - memory integer NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE systems.platforms OWNER TO starrs_admin; - --- --- Name: TABLE platforms; Type: COMMENT; Schema: systems; Owner: starrs_admin --- - -COMMENT ON TABLE platforms IS 'Platform templates of a system'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_platform(text, text, text, text, integer); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_platform(input_name text, input_architecture text, input_disk text, input_cpu text, input_memory integer) RETURNS SETOF systems.platforms - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission denied to create platform: not admin'; - END IF; - - INSERT INTO "systems"."platforms" ("platform_name","architecture","disk","cpu","memory") - VALUES (input_name, input_architecture, input_disk, input_cpu, input_memory); - - PERFORM api.syslog('create_platform:"'||input_name||'"'); - RETURN QUERY (SELECT * FROM "systems"."platforms" WHERE "platform_name" = input_name); - END; -$$; - - -ALTER FUNCTION api.create_platform(input_name text, input_architecture text, input_disk text, input_cpu text, input_memory integer) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_platform(input_name text, input_architecture text, input_disk text, input_cpu text, input_memory integer); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_platform(input_name text, input_architecture text, input_disk text, input_cpu text, input_memory integer) IS 'Create a new hardware platform'; - - -SET search_path = ip, pg_catalog; - --- --- Name: range_groups; Type: TABLE; Schema: ip; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE range_groups ( - range_name text NOT NULL, - group_name text NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE ip.range_groups OWNER TO starrs_admin; - --- --- Name: TABLE range_groups; Type: COMMENT; Schema: ip; Owner: starrs_admin --- - -COMMENT ON TABLE range_groups IS 'Associate ranges to groups of users'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_range_group(text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_range_group(input_range text, input_group text) RETURNS SETOF ip.range_groups - LANGUAGE plpgsql - AS $$ - BEGIN - -- Privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Only admins can assign range resources to groups'; - END IF; - - -- Create - INSERT INTO "ip"."range_groups" ("range_name","group_name") VALUES (input_range, input_group); - - -- Return - PERFORM api.syslog('create_range_group:"'||input_range||'","'||input_group||'"'); - RETURN QUERY (SELECT * FROM "ip"."range_groups" WHERE "group_name" = input_group AND "range_name" = input_range); - END; -$$; - - -ALTER FUNCTION api.create_range_group(input_range text, input_group text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_range_group(input_range text, input_group text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_range_group(input_range text, input_group text) IS 'Assign a range to a group'; - - -SET search_path = management, pg_catalog; - --- --- Name: configuration; Type: TABLE; Schema: management; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE configuration ( - option text NOT NULL, - value text NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE management.configuration OWNER TO starrs_admin; - --- --- Name: TABLE configuration; Type: COMMENT; Schema: management; Owner: starrs_admin --- - -COMMENT ON TABLE configuration IS 'Site specific configuration directives'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_site_configuration(text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_site_configuration(input_directive text, input_value text) RETURNS SETOF management.configuration - LANGUAGE plpgsql - AS $$ - BEGIN - - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission denied. Only admins can create site directives'; - END IF; - - -- Create directive - INSERT INTO "management"."configuration" VALUES (input_directive, input_value); - - -- Done - PERFORM api.syslog('create_site_configuration:"'||input_directive||'","'||input_value||'"'); - RETURN QUERY (SELECT * FROM "management"."configuration" WHERE "option" = input_directive AND "value" = input_value); - END; -$$; - - -ALTER FUNCTION api.create_site_configuration(input_directive text, input_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_site_configuration(input_directive text, input_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_site_configuration(input_directive text, input_value text) IS 'Create a new site configuration directive'; - - -SET search_path = systems, pg_catalog; - --- --- Name: systems; Type: TABLE; Schema: systems; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE systems ( - system_name text NOT NULL, - owner text NOT NULL, - "group" text DEFAULT api.get_site_configuration('DEFAULT_LOCAL_USER_GROUP'::text) NOT NULL, - comment text, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - type text, - os_name text, - last_modifier text NOT NULL, - platform_name text NOT NULL, - asset text, - datacenter text DEFAULT api.get_site_configuration('DEFAULT_DATACENTER'::text) NOT NULL, - location text -); - - -ALTER TABLE systems.systems OWNER TO starrs_admin; - --- --- Name: TABLE systems; Type: COMMENT; Schema: systems; Owner: starrs_admin --- - -COMMENT ON TABLE systems IS 'Systems are devices that connect to the network.'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_system(text, text, text, text, text, text, text, text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_system(input_system_name text, input_owner text, input_type text, input_os_name text, input_comment text, input_group text, input_platform text, input_asset text, input_datacenter text, input_location text) RETURNS SETOF systems.systems - LANGUAGE plpgsql - AS $$ - BEGIN - -- Validate input - input_system_name := api.validate_name(input_system_name); - - -- Fill in username - IF input_owner IS NULL THEN - input_owner := api.get_current_user(); - END IF; - - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF input_owner != api.get_current_user() THEN - RAISE EXCEPTION 'Only administrators can define a different owner (%).',input_owner; - END IF; - END IF; - - -- Insert new system - INSERT INTO "systems"."systems" - ("system_name","owner","type","os_name","comment","last_modifier","group","platform_name","asset","datacenter","location") VALUES - (input_system_name,input_owner,input_type,input_os_name,input_comment,api.get_current_user(),input_group,input_platform,input_asset,input_datacenter,input_location); - - -- Done - PERFORM api.syslog('create_system:"'||input_system_name||'"'); - RETURN QUERY (SELECT * FROM "systems"."systems" WHERE "system_name" = input_system_name); - END; -$$; - - -ALTER FUNCTION api.create_system(input_system_name text, input_owner text, input_type text, input_os_name text, input_comment text, input_group text, input_platform text, input_asset text, input_datacenter text, input_location text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_system(input_system_name text, input_owner text, input_type text, input_os_name text, input_comment text, input_group text, input_platform text, input_asset text, input_datacenter text, input_location text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_system(input_system_name text, input_owner text, input_type text, input_os_name text, input_comment text, input_group text, input_platform text, input_asset text, input_datacenter text, input_location text) IS 'Create a new system'; - - --- --- Name: create_system_quick(text, text, text, macaddr, inet, text, text, boolean); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_system_quick(input_system_name text, input_owner text, input_group text, input_mac macaddr, input_address inet, input_zone text, input_config text, input_dns boolean) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - PERFORM api.create_system( - input_system_name, - input_owner, - api.get_site_configuration('DEFAULT_SYSTEM_TYPE'), - 'Other', - null, - input_group, - api.get_site_configuration('DEFAULT_SYSTEM_PLATFORM'), - null, - api.get_site_configuration('DEFAULT_DATACENTER'), - null - ); - PERFORM api.create_interface( - input_system_name, - input_mac, - api.get_site_configuration('DEFAULT_INTERFACE_NAME'), - null - ); - PERFORM api.create_interface_address( - input_mac, - input_address, - input_config, - api.get_site_configuration('DHCPD_DEFAULT_CLASS'), - TRUE, - null, - null - ); - IF input_dns IS TRUE THEN - PERFORM api.create_dns_address( - input_address, - lower(regexp_replace(input_system_name,' ','-')), - input_zone, - null, - null, - TRUE, - input_owner - ); - END IF; - END; -$$; - - -ALTER FUNCTION api.create_system_quick(input_system_name text, input_owner text, input_group text, input_mac macaddr, input_address inet, input_zone text, input_config text, input_dns boolean) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_system_quick(input_system_name text, input_owner text, input_group text, input_mac macaddr, input_address inet, input_zone text, input_config text, input_dns boolean); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_system_quick(input_system_name text, input_owner text, input_group text, input_mac macaddr, input_address inet, input_zone text, input_config text, input_dns boolean) IS 'Create a full system in one call'; - - -SET search_path = network, pg_catalog; - --- --- Name: vlans; Type: TABLE; Schema: network; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE vlans ( - datacenter text NOT NULL, - vlan integer NOT NULL, - name text NOT NULL, - comment text, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE network.vlans OWNER TO starrs_admin; - --- --- Name: TABLE vlans; Type: COMMENT; Schema: network; Owner: starrs_admin --- - -COMMENT ON TABLE vlans IS 'VLANs in the organization'; - - -SET search_path = api, pg_catalog; - --- --- Name: create_vlan(text, integer, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION create_vlan(input_datacenter text, input_vlan integer, input_name text, input_comment text) RETURNS SETOF network.vlans - LANGUAGE plpgsql - AS $$ - BEGIN - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Only admins can create VLANs'; - END IF; - - INSERT INTO "network"."vlans" ("datacenter","vlan","name","comment") - VALUES (input_datacenter, input_vlan, input_name, input_comment); - - PERFORM api.syslog('create_vlan:"'||input_datacenter||'","'||input_vlan||'"'); - RETURN QUERY (SELECT * FROM "network"."vlans" WHERE "datacenter" = input_datacenter AND "vlan" = input_vlan); - END; -$$; - - -ALTER FUNCTION api.create_vlan(input_datacenter text, input_vlan integer, input_name text, input_comment text) OWNER TO starrs_admin; - --- --- Name: FUNCTION create_vlan(input_datacenter text, input_vlan integer, input_name text, input_comment text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION create_vlan(input_datacenter text, input_vlan integer, input_name text, input_comment text) IS 'Create a VLAN'; - - --- --- Name: deinitialize(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION deinitialize() RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - DROP TABLE IF EXISTS "user_privileges"; - END; -$$; - - -ALTER FUNCTION api.deinitialize() OWNER TO starrs_admin; - --- --- Name: FUNCTION deinitialize(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION deinitialize() IS 'Reset user permissions to activate a new user'; - - --- --- Name: dns_clean_zone_a(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION dns_clean_zone_a(input_zone text) RETURNS void - LANGUAGE plpgsql - AS $_$ - DECLARE - AuditData RECORD; - DnsKeyName TEXT; - DnsKey TEXT; - DnsServer INET; - DnsRecord TEXT; - ReturnCode TEXT; - - BEGIN - - IF (api.get_current_user_level() !~* 'ADMIN') THEN - RAISE EXCEPTION 'Non-admin users are not allowed to clean zones'; - END IF; - - SELECT "dns"."keys"."keyname","dns"."keys"."key","address" - INTO DnsKeyName, DnsKey, DnsServer - FROM "dns"."ns" - JOIN "dns"."zones" ON "dns"."ns"."zone" = "dns"."zones"."zone" - JOIN "dns"."keys" ON "dns"."zones"."keyname" = "dns"."keys"."keyname" - WHERE "dns"."ns"."zone" = input_zone AND "dns"."ns"."nameserver" IN (SELECT "nameserver" FROM "dns"."soa" WHERE "dns"."soa"."zone" = input_zone); - - FOR AuditData IN ( - SELECT - "audit_data"."address", - "audit_data"."type", - "host" AS "bind-forward", - "dns"."a"."hostname"||'.'||"dns"."a"."zone" AS "impulse-forward" - FROM api.dns_zone_audit(input_zone) AS "audit_data" - LEFT JOIN "dns"."a" ON "dns"."a"."address" = "audit_data"."address" - WHERE "audit_data"."type" ~* '^A|AAAA$' - ORDER BY "audit_data"."address" - ) LOOP - -- Delete the forward - DnsRecord := AuditData."bind-forward"; - ReturnCode := api.nsupdate(input_zone,DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - IF ReturnCode != '0' THEN - RAISE EXCEPTION 'DNS Error: % when deleting forward %',ReturnCode,DnsRecord; - END IF; - - -- If it's static, create the correct one - IF (SELECT "config" FROM "systems"."interface_addresses" WHERE "address" = AuditData."address") ~* 'static' AND AuditData."impulse-forward" IS NOT NULL THEN - -- Forward - DnsRecord := AuditData."impulse-forward"||' '||AuditData."ttl"||' '||AuditData."type"||' '||host(AuditData."address"); - ReturnCode := api.nsupdate(input_zone,DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - IF ReturnCode != '0' THEN - RAISE EXCEPTION 'DNS Error: % when creating forward %',ReturnCode,DnsRecord; - END IF; - END IF; - END LOOP; - - END; -$_$; - - -ALTER FUNCTION api.dns_clean_zone_a(input_zone text) OWNER TO starrs_admin; - --- --- Name: FUNCTION dns_clean_zone_a(input_zone text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION dns_clean_zone_a(input_zone text) IS 'Erase all non-IMPULSE controlled A records from a zone.'; - - --- --- Name: dns_clean_zone_ptr(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION dns_clean_zone_ptr(input_zone text) RETURNS void - LANGUAGE plpgsql - AS $$ - DECLARE - AuditData RECORD; - DnsKeyName TEXT; - DnsKey TEXT; - DnsServer INET; - DnsRecord TEXT; - ReturnCode TEXT; - - BEGIN - - IF (api.get_current_user_level() !~* 'ADMIN') THEN - RAISE EXCEPTION 'Non-admin users are not allowed to clean zones'; - END IF; - - SELECT "dns"."keys"."keyname","dns"."keys"."key","dns"."ns"."address" - INTO DnsKeyName, DnsKey, DnsServer - FROM "dns"."ns" - JOIN "dns"."zones" ON "dns"."ns"."zone" = "dns"."zones"."zone" - JOIN "dns"."keys" ON "dns"."zones"."keyname" = "dns"."keys"."keyname" - JOIN "dns"."soa" ON "dns"."soa"."zone" = "dns"."ns"."zone" - WHERE "dns"."ns"."nameserver" = "dns"."soa"."nameserver" - AND "dns"."ns"."zone" = (SELECT "ip"."subnets"."zone" FROM "ip"."subnets" WHERE api.get_reverse_domain("subnet") = input_zone); - - FOR AuditData IN ( - SELECT - "audit_data"."host", - "audit_data"."target" AS "bind-reverse", - "dns"."a"."hostname"||'.'||"dns"."a"."zone" AS "impulse-reverse", - "dns"."a"."ttl" AS "ttl", - "audit_data"."type" AS "type" - FROM api.dns_zone_audit(input_zone) AS "audit_data" - LEFT JOIN "dns"."a" ON api.get_reverse_domain("dns"."a"."address") = "audit_data"."host" - WHERE "audit_data"."type"='PTR' - ) LOOP - DnsRecord := AuditData."host"; - ReturnCode := api.nsupdate(input_zone,DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - IF ReturnCode != '0' THEN - RAISE EXCEPTION 'DNS Error: % when deleting reverse %',ReturnCode,DnsRecord; - END IF; - - IF (SELECT "config" FROM "systems"."interface_addresses" WHERE api.get_reverse_domain("address") = AuditData."host") ~* 'static' AND AuditData."impulse-reverse" IS NOT NULL THEN - DnsRecord := AuditData."host"||' '||AuditData."ttl"||' '||AuditData."type"||' '||AuditData."impulse-reverse"; - ReturnCode := api.nsupdate(input_zone,DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - IF ReturnCode != '0' THEN - RAISE EXCEPTION 'DNS Error: % when creating reverse %',ReturnCode,DnsRecord; - END IF; - END IF; - - END LOOP; - END; -$$; - - -ALTER FUNCTION api.dns_clean_zone_ptr(input_zone text) OWNER TO starrs_admin; - --- --- Name: FUNCTION dns_clean_zone_ptr(input_zone text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION dns_clean_zone_ptr(input_zone text) IS 'Clean all incorrect pointer records in a reverse zone'; - - --- --- Name: dns_forward_lookup(text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION dns_forward_lookup(text) RETURNS inet - LANGUAGE plperlu - AS $_X$ - use Socket; - - my $hostname = $_[0]; - #my $ipaddr = `host $hostname | cut -d ' ' -f 4`; - $packed_ip = gethostbyname("$hostname"); - if (defined $packed_ip) { - $ip_address = inet_ntoa($packed_ip); - } - return $ip_address; -$_X$; - - -ALTER FUNCTION api.dns_forward_lookup(text) OWNER TO postgres; - --- --- Name: dns_resolve(text, text, integer); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION dns_resolve(input_hostname text, input_zone text, input_family integer) RETURNS inet - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_family IS NULL THEN - RETURN (SELECT "address" FROM "dns"."a" WHERE "hostname" = input_hostname AND "zone" = input_zone LIMIT 1); - ELSE - RETURN (SELECT "address" FROM "dns"."a" WHERE "hostname" = input_hostname AND "zone" = input_zone AND family("address") = input_family); - END IF; - END; -$$; - - -ALTER FUNCTION api.dns_resolve(input_hostname text, input_zone text, input_family integer) OWNER TO starrs_admin; - --- --- Name: FUNCTION dns_resolve(input_hostname text, input_zone text, input_family integer); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION dns_resolve(input_hostname text, input_zone text, input_family integer) IS 'Resolve a hostname/zone to its IP address'; - - --- --- Name: dns_zone_audit(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION dns_zone_audit(input_zone text) RETURNS SETOF dns.zone_audit_data - LANGUAGE plpgsql - AS $$ - BEGIN - -- Create a temporary table to store record data in - DROP TABLE IF EXISTS "audit"; - CREATE TEMPORARY TABLE "audit" ( - host TEXT, ttl INTEGER, type TEXT, address INET, port INTEGER, weight INTEGER, priority INTEGER, preference INTEGER, target TEXT, text TEXT, contact TEXT, serial TEXT, refresh INTEGER, retry INTEGER, expire INTEGER, minimum INTEGER); - - -- Put AXFR data into the table - IF (SELECT "forward" FROM "dns"."zones" WHERE "zone" = input_zone) IS TRUE THEN - INSERT INTO "audit" - (SELECT * FROM "api"."query_axfr"(input_zone, (SELECT "nameserver" FROM "dns"."soa" WHERE "zone" = input_zone))); - ELSE - INSERT INTO "audit" (SELECT * FROM "api"."query_axfr"(input_zone, (SELECT "nameserver" FROM "dns"."soa" WHERE "zone" = (SELECT "zone" FROM "ip"."subnets" WHERE api.get_reverse_domain("subnet") = input_zone)))); - END IF; - - -- Update the SOA table with the latest serial - PERFORM api.modify_dns_soa(input_zone,'serial',(SELECT "api"."query_zone_serial"(input_zone))); - - IF (SELECT "forward" FROM "dns"."zones" WHERE "zone" = input_zone) IS TRUE THEN - -- Remove all records that IMPULSE contains - DELETE FROM "audit" WHERE ("host","ttl","type","address") IN (SELECT "hostname"||'.'||"zone" AS "host","ttl","type","address" FROM "dns"."a"); - DELETE FROM "audit" WHERE ("host","ttl","type","target","port","weight","priority") IN (SELECT "alias"||'.'||"zone" AS "host","ttl","type","hostname"||'.'||"zone" as "target","port","weight","priority" FROM "dns"."srv"); - DELETE FROM "audit" WHERE ("host","ttl","type","target") IN (SELECT "alias"||'.'||"zone" AS "host","ttl","type","hostname"||'.'||"zone" as "target" FROM "dns"."cname"); - DELETE FROM "audit" WHERE ("host","ttl","type","preference") IN (SELECT "hostname"||'.'||"zone" AS "host","ttl","type","preference" FROM "dns"."mx"); - DELETE FROM "audit" WHERE ("host","ttl","type") IN (SELECT "nameserver" AS "host","ttl","type" FROM "dns"."ns"); - DELETE FROM "audit" WHERE ("host","ttl","type","text") IN (SELECT "hostname"||'.'||"zone" AS "host","ttl","type","text" FROM "dns"."txt"); - DELETE FROM "audit" WHERE ("host","ttl","type","target","contact","serial","refresh","retry","expire","minimum") IN - (SELECT "zone" as "host","ttl",'SOA'::text as "type","nameserver" as "target","contact","serial","refresh","retry","expire","minimum" FROM "dns"."soa"); - DELETE FROM "audit" WHERE ("host","ttl","type","text") IN (SELECT "hostname"||'.'||"zone" AS "host","ttl","type","text" FROM "dns"."zone_txt"); - DELETE FROM "audit" WHERE ("host","ttl","type","text") IN (SELECT "zone" AS "host","ttl","type","text" FROM "dns"."zone_txt"); - DELETE FROM "audit" WHERE ("host","ttl","type","address") IN (SELECT "zone" AS "host","ttl","type","address" FROM "dns"."zone_a"); - - -- DynamicDNS records have TXT data placed by the DHCP server. Don't count those. - DELETE FROM "audit" WHERE ("host") IN (SELECT "hostname"||'.'||"zone" AS "host" FROM "api"."get_dhcpd_dynamic_hosts"() WHERE "hostname" IS NOT NULL) AND "type" = 'TXT'; - -- So do DHCP'd records; - DELETE FROM "audit" WHERE ("host") IN (SELECT "hostname"||'.'||"zone" AS "host" FROM "dns"."a" JOIN "systems"."interface_addresses" ON "systems"."interface_addresses"."address" = "dns"."a"."address" WHERE "config"='dhcp') AND "type"='TXT'; - ELSE - -- Remove constant address records - DELETE FROM "audit" WHERE ("host","target","type") IN (SELECT api.get_reverse_domain("address") as "host","hostname"||'.'||"zone" as "target",'PTR'::text AS "type" FROM "dns"."a"); - -- Remove Dynamics - DELETE FROM "audit" WHERE ("target","type") IN (SELECT "hostname"||'.'||"zone" as "target",'PTR'::text AS "type" FROM "dns"."a" JOIN "systems"."interface_addresses" ON "systems"."interface_addresses"."address" = "dns"."a"."address" WHERE "config"='dhcp'); - -- Remove NS records; - DELETE FROM "audit" WHERE ("host","ttl","type") IN (SELECT "nameserver" AS "host","ttl","type" FROM "dns"."ns"); - -- Remove SOA; - DELETE FROM "audit" WHERE ("host","ttl","type","target","contact","serial","refresh","retry","expire","minimum") IN - (SELECT "zone" as "host","ttl",'SOA'::text as "type","nameserver" as "target","contact","serial","refresh","retry","expire","minimum" FROM "dns"."soa" WHERE "zone" = input_zone); - -- Remove TXT - DELETE FROM "audit" WHERE ("host","ttl","type","text") IN (SELECT "hostname"||'.'||"zone" AS "host","ttl","type","text" FROM "dns"."zone_txt"); - DELETE FROM "audit" WHERE ("host","ttl","type","text") IN (SELECT "zone" AS "host","ttl","type","text" FROM "dns"."zone_txt"); - END IF; - - -- What's left is data that IMPULSE has no idea of - RETURN QUERY (SELECT * FROM "audit"); - END; -$$; - - -ALTER FUNCTION api.dns_zone_audit(input_zone text) OWNER TO starrs_admin; - --- --- Name: FUNCTION dns_zone_audit(input_zone text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION dns_zone_audit(input_zone text) IS 'Perform an audit of IMPULSE zone data against server zone data'; - - --- --- Name: exec(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION exec(text) RETURNS void - LANGUAGE plpgsql - AS $_$ - BEGIN - EXECUTE $1; - END; -$_$; - - -ALTER FUNCTION api.exec(text) OWNER TO starrs_admin; - --- --- Name: FUNCTION exec(text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION exec(text) IS 'Execute a query in a plpgsql context'; - - --- --- Name: generate_dhcpd6_config(); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION generate_dhcpd6_config() RETURNS void - LANGUAGE plperlu - AS $_X$ - # Script written by Anthony Gargiulo - # Altered for IPv6 by Jordan Rodgers - use warnings; - no warnings 'redefine'; - - # First things first. defining the subroutines that make up this script. - - # Global Options - sub global_opts - { - my ($row, $option, $value, $output); - my $global_options = spi_query("SELECT * FROM api.get_dhcpd_global_options()"); - while (defined($row = spi_fetchrow($global_options))) - { - $option = $row->{option}; - $value = $row->{value}; - $output .= "$option $value;\n" - } - return $output; - } # end global options - - # DNS keys added here - sub dns_keys - { - my $keys = spi_query("SELECT * FROM api.get_dhcpd_dns_keys()"); - my ($keyname, $key, $enctype, $row, $output); - while (defined ($row = spi_fetchrow($keys))) - { - $keyname = $row->{keyname}; - $key = $row->{key}; - $enctype = $row->{enctype}; - $output .= "key $keyname {\n algorithm ${enctype};\n secret \"$key\";\n}\n"; - } - return $output; - }# end DNS keys - - # Zones are added here. - sub forward_zones - { - my $zones = spi_query("SELECT * FROM api.get_dhcpd_forward_zones()"); - my ($zone, $keyname, $primary_ns, $row, $output); - $output = ""; - while (defined ($row = spi_fetchrow($zones))) - { - $zone = $row->{zone}; - $keyname = $row->{keyname}; - $primary_ns = $row->{primary_ns}; - $output .= "zone $zone {\n primary ${primary_ns};\n key ${keyname};\n}\n"; - } - return $output; - }# end forward zones - - # Zones are added here. - sub reverse_zones - { - my $zones = spi_query("SELECT * FROM api.get_dhcpd6_reverse_zones()"); - my ($zone, $keyname, $primary_ns, $row, $output); - $output = ""; - while (defined ($row = spi_fetchrow($zones))) - { - $zone = $row->{zone}; - $keyname = $row->{keyname}; - $primary_ns = $row->{primary_ns}; - $output .= "zone $zone {\n primary ${primary_ns};\n key ${keyname};\n}\n"; - } - return $output; - }# end reverse zones - - # DHCP Classes - sub dhcp_classes - { - my $classes = spi_query("SELECT class,comment FROM api.get_dhcpd_classes()"); - my ($class, $comment, $row, $output); - while (defined($row = spi_fetchrow($classes))) - { - $class = $row->{class}; - $comment = $row->{comment}; - $output .= "class \"$class\" {\n"; - $output .= " # ${comment}\n" if(defined($comment)); - $output .= &dhcp_class_options($class); - $output .= "}\n\n"; - } - return $output; - }# end &dhcp_classes - - # DHCP Class options - sub dhcp_class_options - { - my $class = $_[0]; - my $options = spi_query("SELECT * FROM api.get_dhcpd_class_options('$class')"); - my ($option, $value, $row, $output); - while (defined($row = spi_fetchrow($options))) - { - $option = $row->{option}; - $value = $row->{value}; - $output .= " " . $option . ' ' . $value . ";\n"; - } - return $output; - }# end &dhcp_class_options - - # Shared networks - sub shared_networks - { - my $networks = spi_query("SELECT get_dhcpd_shared_networks FROM api.get_dhcpd_shared_networks()"); - my ($network, $row, $output, $subnets); - - while (defined($row = spi_fetchrow($networks))) - { - $network = $row->{get_dhcpd_shared_networks}; - $subnets = &subnets($network); - if ($subnets) - { - $output .= "shared-network " . $network . " {\n\n"; - $output .= $subnets; - $output .= "}\n\n"; - } - } - return $output; - } - - # Subnets (for shared networks) - sub subnets - { - my $shared_net = $_[0]; - # COHOE: THIS QUERY STRING IS QUITE VERBOSE, I HOPE YOU ARE HAPPY - my $query = "select get_dhcpd_shared_network_subnets as subnets, netmask(get_dhcpd_shared_network_subnets) "; - $query .= "from api.get_dhcpd_shared_network_subnets('$shared_net')"; - my $subnets = spi_query($query); - - # $subnet = ip + netmask in slash notation; i.e. 10.21.49.0/24 - # $net = only the network address; i.e. 10.21.49.0 - # $mask = netmask in dotted decimal notation; i.e. 255.255.255.0 - my ($subnet, $net, $mask, $row, $output); - - while (defined($row = spi_fetchrow($subnets))) - { - $subnet = $row->{subnets}; - # Dirty way to only do IPv6 subnets - if (index($subnet, ':') != -1) - { - $net = substr($subnet, 0, index($subnet, "/")); - $mask = $row->{netmask}; - $output .= " subnet6 $subnet {\n "; - $output .= " authoritative;"; - my $subnet_option = &subnet_options($subnet); - if(defined($subnet_option)) - { - $output .= $subnet_option; - } - my $subnet_range = &subnet_ranges($subnet); - if(defined($subnet_range)) - { - $output .= $subnet_range; - } - $output .= "\n }\n\n"; - } - } - return $output; - } - - # Subnet options - sub subnet_options - { - my $subnet = $_[0]; - my $options = spi_query("SELECT option,value from api.get_dhcpd_subnet_options('$subnet')"); - my ($option, $value, $row, $output); - while (defined($row = spi_fetchrow($options))) - { - $option = $row->{option}; - $value = $row->{value}; - $output .= "\n $option $value;"; - } - return $output; - } - - # Subnet ranges - sub subnet_ranges - { - my $subnet = $_[0]; - my $pool = spi_query("SELECT name,first_ip,last_ip,class from api.get_dhcpd_subnet_ranges('$subnet')"); - my ($range_name, $first_ip, $last_ip, $class, $row, $output); - $output=""; - - while (defined($row = spi_fetchrow($pool))) - { - $range_name = $row->{name}; - $first_ip = $row->{first_ip}; - $last_ip = $row->{last_ip}; - $class = $row->{class}; - $output .= "\n pool {\n range $first_ip $last_ip;\n failover peer \"dhcpfailover\";"; - { - my $range_options = spi_query("SELECT * from api.get_dhcpd_range_options('$range_name')"); - my ($option, $value, $row); - while (defined($row = spi_fetchrow($range_options))) - { - $option = $row->{option}; - $value = $row->{value}; - $output .= "\n $option $value;"; - } - } - if (defined($class)) - { - $output .= "\n allow members of \"$class\";"; - } - else - { - $output .= "\n allow unknown clients;"; - } - $output .= "\n }"; - } - return $output; - } - - # hosts - sub hosts - { - my $static_hosts = spi_query("SELECT * FROM api.get_dhcpd6_static_hosts() order by owner,hostname"); - # Disable dynamic hosts - #my $dynamic_hosts = spi_query("SELECT * FROM api.get_dhcpd_dynamic_hosts() order by owner,hostname"); - my ($hostname, $zone, $mac, $address, $owner, $class, $row, $output); - $output .= "# Static hosts\n"; - while (defined($row = spi_fetchrow($static_hosts))) - { - $hostname = $row->{hostname}; - $zone = $row->{zone}; - $mac = $row->{mac}; - $address = $row->{address}; - $owner = $row->{owner}; - $class = $row->{class}; - - # Dirty way to only do IPv6 hosts - if (index($address, ':') != -1) - { - $output .= &host_config($hostname, $zone, $mac, $address, $owner, $class); - } - } - # Disable dynamic hosts - #$output .= "# Dynamic hosts\n"; - #while (defined($row = spi_fetchrow($dynamic_hosts))) - #{ - # $hostname = $row->{hostname}; - # $zone = $row->{zone}; - # $mac = $row->{mac}; - # $owner = $row->{owner}; - # $class = $row->{class}; - # - # # Dirty way to only do IPv6 hosts - # if (index($address, ':') != -1) - # { - # $output .= &host_config($hostname, $zone, $mac, undef, $owner, $class); - # } - #} - return $output; - } - - # hosts config generation - sub host_config - { - my ($hostname, $zone, $mac, $address, $owner, $class) = @_; - - my $hostmac = $mac; - $hostmac =~ s/://g; - - my $output .= "# $owner\n"; - if (defined($hostname) && defined($zone)) - { - $output .= "host $hostname.$zone {\n"; - }else - { - $output .= "host $hostmac {\n"; - } - $output .= " option dhcp-client-identifier 1:$mac;\n"; - $output .= " hardware ethernet $mac;\n"; - $output .= " fixed-address6 $address;\n" if (defined($address)); - $output .= " option host-name \"$hostname\";\n" if (defined($hostname)); - $output .= " ddns-hostname \"$hostname\";\n" if (defined($hostname)); - $output .= " ddns-domainname \"$zone\";\n" if (defined($zone)); - $output .= " option domain-name \"$zone\";\n" if (defined($zone)); - $output .= "}\n"; - $output .= "subclass \"$class\" 1:$mac;\n"; - $output .= "subclass \"$class\" $mac;\n\n"; - return $output; - } - - - # lets start with the DHCPd.conf header from the DB - my $header = spi_exec_query("SELECT api.get_site_configuration('DHCPD6_HEADER')"); - my $output = $header->{rows}[0]->{get_site_configuration}. "\n\n"; - - # add the date to the file - my $date = spi_exec_query("SELECT localtimestamp(0)")->{rows}[0]->{timestamp}; - $output .= "\# Generated at $date\n\n"; - - # now for the rest of the config file - $output .= &global_opts() . "\n"; - $output .= &dns_keys() . "\n"; - $output .= &forward_zones() . "\n"; - $output .= &reverse_zones() . "\n"; - $output .= &dhcp_classes() . "\n"; - $output .= &shared_networks() . "\n"; - $output .= &hosts() . "\n"; - - $output .= "\# End dhcpd6 configuration file"; - - # finally, store the config in the db, so we can get it back later. - spi_exec_query("INSERT INTO management.output (value,file,timestamp) VALUES (\$\$".$output."\$\$,'dhcpd6.conf',now())"); - - #log our success with the api logging tool. - spi_exec_query("SELECT api.syslog('successfully generated dhcpd6.conf')"); -$_X$; - - -ALTER FUNCTION api.generate_dhcpd6_config() OWNER TO postgres; - --- --- Name: FUNCTION generate_dhcpd6_config(); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION generate_dhcpd6_config() IS 'Generate the config file for the dhcpd6 server, and store it in the db'; - - --- --- Name: generate_dhcpd_config(); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION generate_dhcpd_config() RETURNS void - LANGUAGE plperlu - AS $_X$ - # Script written by Anthony Gargiulo - use strict; - use warnings; - no warnings 'redefine'; - - # First things first. defining the subroutines that make up this script. - - # Global Options - sub global_opts - { - my ($row, $option, $value, $output); - my $global_options = spi_query("SELECT * FROM api.get_dhcpd_global_options()"); - while (defined($row = spi_fetchrow($global_options))) - { - $option = $row->{option}; - $value = $row->{value}; - $output .= "$option $value;\n" - } - return $output; - } # end global options - - # DNS keys added here - sub dns_keys - { - my $keys = spi_query("SELECT * FROM api.get_dhcpd_dns_keys()"); - my ($keyname, $key, $enctype, $row, $output); - while (defined ($row = spi_fetchrow($keys))) - { - $keyname = $row->{keyname}; - $key = $row->{key}; - $enctype = $row->{enctype}; - $output .= "key $keyname {\n algorithm ${enctype};\n secret \"$key\";\n}\n"; - } - return $output; - }# end DNS keys - - # Zones are added here. - sub forward_zones - { - my $zones = spi_query("SELECT * FROM api.get_dhcpd_forward_zones()"); - my ($zone, $keyname, $primary_ns, $row, $output); - $output = ""; - while (defined ($row = spi_fetchrow($zones))) - { - $zone = $row->{zone}; - $keyname = $row->{keyname}; - $primary_ns = $row->{primary_ns}; - $output .= "zone $zone {\n primary ${primary_ns};\n key ${keyname};\n}\n"; - } - return $output; - }# end forward zones - - # Zones are added here. - sub reverse_zones - { - my $zones = spi_query("SELECT * FROM api.get_dhcpd_reverse_zones()"); - my ($zone, $keyname, $primary_ns, $row, $output); - $output = ""; - while (defined ($row = spi_fetchrow($zones))) - { - $zone = $row->{zone}; - $keyname = $row->{keyname}; - $primary_ns = $row->{primary_ns}; - $output .= "zone $zone {\n primary ${primary_ns};\n key ${keyname};\n}\n"; - } - return $output; - }# end reverse zones - - # DHCP Classes - sub dhcp_classes - { - my $classes = spi_query("SELECT class,comment FROM api.get_dhcpd_classes()"); - my ($class, $comment, $row, $output); - while (defined($row = spi_fetchrow($classes))) - { - $class = $row->{class}; - $comment = $row->{comment}; - $output .= "class \"$class\" {\n"; - $output .= " # ${comment}\n" if(defined($comment)); - $output .= &dhcp_class_options($class); - $output .= "}\n\n"; - } - return $output; - }# end &dhcp_classes - - # DHCP Class options - sub dhcp_class_options - { - my $class = $_[0]; - my $options = spi_query("SELECT * FROM api.get_dhcpd_class_options('$class')"); - my ($option, $value, $row, $output); - while (defined($row = spi_fetchrow($options))) - { - $option = $row->{option}; - $value = $row->{value}; - $output .= " " . $option . ' ' . $value . ";\n"; - } - return $output; - }# end &dhcp_class_options - - # Shared networks - sub shared_networks - { - my $networks = spi_query("SELECT get_dhcpd_shared_networks FROM api.get_dhcpd_shared_networks()"); - my ($network, $row, $output, $subnets); - - while (defined($row = spi_fetchrow($networks))) - { - $network = $row->{get_dhcpd_shared_networks}; - $subnets = &subnets($network); - if ($subnets) - { - $output .= "shared-network " . $network . " {\n\n"; - $output .= $subnets; - $output .= "}\n\n"; - } - } - return $output; - } - - # Subnets (for shared networks) - sub subnets - { - my $shared_net = $_[0]; - # COHOE: THIS QUERY STRING IS QUITE VERBOSE, I HOPE YOU ARE HAPPY - my $query = "select get_dhcpd_shared_network_subnets as subnets, netmask(get_dhcpd_shared_network_subnets) "; - $query .= "from api.get_dhcpd_shared_network_subnets('$shared_net')"; - my $subnets = spi_query($query); - - # $subnet = ip + netmask in slash notation; i.e. 10.21.49.0/24 - # $net = only the network address; i.e. 10.21.49.0 - # $mask = netmask in dotted decimal notation; i.e. 255.255.255.0 - my ($subnet, $net, $mask, $row, $output); - - while (defined($row = spi_fetchrow($subnets))) - { - $subnet = $row->{subnets}; - $net = substr($subnet, 0, index($subnet, "/")); - $mask = $row->{netmask}; - $output .= " subnet $net netmask $mask {\n "; - $output .= " authoritative;"; - my $subnet_option = &subnet_options($subnet); - if(defined($subnet_option)) - { - $output .= $subnet_option; - } - my $subnet_range = &subnet_ranges($subnet); - if(defined($subnet_range)) - { - $output .= $subnet_range; - } - $output .= "\n }\n\n"; - } - return $output; - } - - # Subnet options - sub subnet_options - { - my $subnet = $_[0]; - my $options = spi_query("SELECT option,value from api.get_dhcpd_subnet_options('$subnet')"); - my ($option, $value, $row, $output); - while (defined($row = spi_fetchrow($options))) - { - $option = $row->{option}; - $value = $row->{value}; - $output .= "\n $option $value;"; - } - return $output; - } - - # Subnet ranges - sub subnet_ranges - { - my $subnet = $_[0]; - my $pool = spi_query("SELECT name,first_ip,last_ip,class from api.get_dhcpd_subnet_ranges('$subnet')"); - my ($range_name, $first_ip, $last_ip, $class, $row, $output); - $output=""; - - while (defined($row = spi_fetchrow($pool))) - { - $range_name = $row->{name}; - $first_ip = $row->{first_ip}; - $last_ip = $row->{last_ip}; - $class = $row->{class}; - $output .= "\n pool {\n range $first_ip $last_ip;"; - { - my $range_options = spi_query("SELECT * from api.get_dhcpd_range_options('$range_name')"); - my ($option, $value, $row); - while (defined($row = spi_fetchrow($range_options))) - { - $option = $row->{option}; - $value = $row->{value}; - $output .= "\n $option $value;"; - } - } - if (defined($class)) - { - $output .= "\n allow members of \"$class\";"; - } - else - { - $output .= "\n allow unknown clients;"; - } - $output .= "\n }"; - } - return $output; - } - - # hosts - sub hosts - { - my $static_hosts = spi_query("SELECT * FROM api.get_dhcpd_static_hosts() order by owner,hostname"); - my $dynamic_hosts = spi_query("SELECT * FROM api.get_dhcpd_dynamic_hosts() order by owner,hostname"); - my ($hostname, $zone, $mac, $address, $owner, $class, $row, $output); - $output .= "# Static hosts\n"; - while (defined($row = spi_fetchrow($static_hosts))) - { - $hostname = $row->{hostname}; - $zone = $row->{zone}; - $mac = $row->{mac}; - $address = $row->{address}; - $owner = $row->{owner}; - $class = $row->{class}; - - $output .= &host_config($hostname, $zone, $mac, $address, $owner, $class); - } - $output .= "# Dynamic hosts\n"; - while (defined($row = spi_fetchrow($dynamic_hosts))) - { - $hostname = $row->{hostname}; - $zone = $row->{zone}; - $mac = $row->{mac}; - $owner = $row->{owner}; - $class = $row->{class}; - - $output .= &host_config($hostname, $zone, $mac, undef, $owner, $class); - } - return $output; - } - - # hosts config generation - sub host_config - { - my ($hostname, $zone, $mac, $address, $owner, $class) = @_; - - my $hostmac = $mac; - $hostmac =~ s/://g; - - my $output .= "# $owner\n"; - if (defined($hostname) && defined($zone)) - { - $output .= "host $hostname.$zone {\n"; - }else - { - $output .= "host $hostmac {\n"; - } - $output .= " option dhcp-client-identifier 1:$mac;\n"; - $output .= " hardware ethernet $mac;\n"; - $output .= " fixed-address $address;\n" if (defined($address)); - $output .= " option host-name \"$hostname\";\n" if (defined($hostname)); - $output .= " ddns-hostname \"$hostname\";\n" if (defined($hostname)); - $output .= " ddns-domainname \"$zone\";\n" if (defined($zone)); - $output .= " option domain-name \"$zone\";\n" if (defined($zone)); - $output .= "}\n"; - $output .= "subclass \"$class\" 1:$mac;\n"; - $output .= "subclass \"$class\" $mac;\n\n"; - return $output; - } - - - # lets start with the DHCPd.conf header from the DB - my $header = spi_exec_query("SELECT api.get_site_configuration('DHCPD_HEADER')"); - my $output = $header->{rows}[0]->{get_site_configuration}. "\n\n"; - - # add the date to the file - my $date = spi_exec_query("SELECT localtimestamp(0)")->{rows}[0]->{timestamp}; - $output .= "\# Generated at $date\n\n"; - - # now for the rest of the config file - $output .= &global_opts() . "\n"; - $output .= &dns_keys() . "\n"; - $output .= &forward_zones() . "\n"; - $output .= &reverse_zones() . "\n"; - $output .= &dhcp_classes() . "\n"; - $output .= &shared_networks() . "\n"; - $output .= &hosts() . "\n"; - - $output .= "\# End dhcpd configuration file"; - - # finally, store the config in the db, so we can get it back later. - spi_exec_query("INSERT INTO management.output (value,file,timestamp) VALUES (\$\$".$output."\$\$,'dhcpd.conf',now())"); - - #log our success with the api logging tool. - spi_exec_query("SELECT api.syslog('successfully generated dhcpd.conf')"); -$_X$; - - -ALTER FUNCTION api.generate_dhcpd_config() OWNER TO postgres; - --- --- Name: FUNCTION generate_dhcpd_config(); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION generate_dhcpd_config() IS 'Generate the config file for the dhcpd server, and store it in the db'; - - --- --- Name: get_ad_user_email(text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION get_ad_user_email(text) RETURNS text - LANGUAGE plperlu - AS $_$ - #!/usr/bin/perl - - use strict; - use warnings; - use Net::LDAPS; - use Data::Dumper; - - my $uri = spi_exec_query("SELECT api.get_site_configuration('AD_URI')")->{rows}[0]->{"get_site_configuration"}; - my $binddn = spi_exec_query("SELECT api.get_site_configuration('AD_BINDDN')")->{rows}[0]->{"get_site_configuration"}; - my $password = spi_exec_query("SELECT api.get_site_configuration('AD_PASSWORD')")->{rows}[0]->{"get_site_configuration"}; - my $identifier= spi_exec_query("SELECT api.get_site_configuration('AD_IDENTIFIER')")->{rows}[0]->{"get_site_configuration"}; - my $username = shift(@_) or die "Unable to get username\n"; - - # Set up the server connection - my $srv = Net::LDAPS->new ($uri) or die "Could not connect to LDAP server ($uri)\n"; - my $mesg = $srv->bind($binddn,password=>$password) or die "Could not bind to LDAP server at $uri\n"; - - # Get the users DN - my $user_dn_query = $srv->search(filter=>"($identifier=$username)"); - my $user_result = $user_dn_query->pop_entry(); - if(!$user_result) { - die "Unable to find user \"$username\"\n"; - } - - # Unbind from the server - $srv->unbind; - - return $user_result->get_value('mail'); -$_$; - - -ALTER FUNCTION api.get_ad_user_email(text) OWNER TO postgres; - --- --- Name: FUNCTION get_ad_user_email(text); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION get_ad_user_email(text) IS 'Get a users email address from Active Directory'; - - --- --- Name: get_ad_user_level(text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION get_ad_user_level(text) RETURNS text - LANGUAGE plperlu - AS $_X$ - #!/usr/bin/perl - - use strict; - use warnings; - use Net::LDAPS; - use Data::Dumper; - - my $uri = spi_exec_query("SELECT api.get_site_configuration('AD_URI')")->{rows}[0]->{"get_site_configuration"}; - my $binddn = spi_exec_query("SELECT api.get_site_configuration('AD_BINDDN')")->{rows}[0]->{"get_site_configuration"}; - my $password = spi_exec_query("SELECT api.get_site_configuration('AD_PASSWORD')")->{rows}[0]->{"get_site_configuration"}; - my $identifier= spi_exec_query("SELECT api.get_site_configuration('AD_IDENTIFIER')")->{rows}[0]->{"get_site_configuration"}; - my $admin_filter = spi_exec_query("SELECT api.get_site_configuration('AD_ADMIN_FILTER')")->{rows}[0]->{"get_site_configuration"}; - my $admin_basedn = spi_exec_query("SELECT api.get_site_configuration('AD_ADMIN_BASEDN')")->{rows}[0]->{"get_site_configuration"}; - my $program_filter = spi_exec_query("SELECT api.get_site_configuration('AD_PROGRAM_FILTER')")->{rows}[0]->{"get_site_configuration"}; - my $program_basedn = spi_exec_query("SELECT api.get_site_configuration('AD_PROGRAM_BASEDN')")->{rows}[0]->{"get_site_configuration"}; - my $user_filter = spi_exec_query("SELECT api.get_site_configuration('AD_USER_FILTER')")->{rows}[0]->{"get_site_configuration"}; - my $user_basedn = spi_exec_query("SELECT api.get_site_configuration('AD_USER_BASEDN')")->{rows}[0]->{"get_site_configuration"}; - my $username = shift(@_) or die "Unable to get username\n"; - - my $status = "NONE"; - my $user_dn; - - if ($username eq "root") { - return "ADMIN"; - } - - - # Set up the server connection - my $srv = Net::LDAPS->new ($uri) or die "Could not connect to LDAP server ($uri)\n"; - my $mesg = $srv->bind($binddn,password=>$password) or die "Could not bind to LDAP server at $uri\n"; - - # Get the users DN - my $user_dn_query = $srv->search(filter=>"($identifier=$username)"); - my $user_result = $user_dn_query->pop_entry(); - if($user_result) { - $user_dn = $user_result->dn; - } else { - die "Unable to identify user \"$username\"\n"; - } - - # Get the User group members - my $user_query = $srv->search(filter=>"($user_filter)",base=>"$user_basedn"); - foreach my $user_user_entries ($user_query->entries) { - if(grep $user_dn eq $_, $user_user_entries->get_value("member")) { - $status = "USER"; - } - } - - # Get the Admin group members - my $admin_query = $srv->search(filter=>"($admin_filter)",base=>"$admin_basedn"); - foreach my $admin_user_entries ($admin_query->entries) { - if(grep $user_dn eq $_, $admin_user_entries->get_value("member")) { - $status = "ADMIN"; - } - } - - # Unbind from the server - $srv->unbind; - - return $status; -$_X$; - - -ALTER FUNCTION api.get_ad_user_level(text) OWNER TO postgres; - --- --- Name: FUNCTION get_ad_user_level(text); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION get_ad_user_level(text) IS 'Get a users level from Active Directory'; - - --- --- Name: get_address_from_range(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_address_from_range(input_range_name text) RETURNS inet - LANGUAGE plpgsql - AS $$ - DECLARE - LowerBound INET; - UpperBound INET; - AddressToUse INET; - BEGIN - -- Dynamic Addressing for ipv4 - IF (SELECT "use" FROM "ip"."ranges" WHERE "name" = input_range_name) = 'ROAM' - AND (SELECT family("subnet") FROM "ip"."ranges" WHERE "name" = input_range_name) = 4 THEN - SELECT "address" INTO AddressToUse FROM "ip"."addresses" - WHERE "address" << cidr(api.get_site_configuration('DYNAMIC_SUBNET')) - AND "address" NOT IN (SELECT "address" FROM "systems"."interface_addresses") ORDER BY "address" ASC LIMIT 1; - RETURN AddressToUse; - END IF; - - -- Get range bounds - SELECT "first_ip","last_ip" INTO LowerBound,UpperBound - FROM "ip"."ranges" - WHERE "ip"."ranges"."name" = input_range_name; - - -- Get address from range - SELECT "address" FROM "ip"."addresses" INTO AddressToUse - WHERE "address" <= UpperBound AND "address" >= LowerBound - AND "address" NOT IN (SELECT "address" FROM "systems"."interface_addresses") ORDER BY "address" ASC LIMIT 1; - - -- Check if range was full (AddressToUse will be NULL) - IF AddressToUse IS NULL THEN - RAISE EXCEPTION 'All addresses in range % are in use',input_range_name; - END IF; - - -- Done - RETURN AddressToUse; - END; -$$; - - -ALTER FUNCTION api.get_address_from_range(input_range_name text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_address_from_range(input_range_name text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_address_from_range(input_range_name text) IS 'get the first available address in a range'; - - --- --- Name: get_address_range(inet); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_address_range(input_address inet) RETURNS text - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN (SELECT "name" FROM "ip"."ranges" WHERE "first_ip" <= input_address AND "last_ip" >= input_address); - END; -$$; - - -ALTER FUNCTION api.get_address_range(input_address inet) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_address_range(input_address inet); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_address_range(input_address inet) IS 'Get the name of the range an address is in'; - - --- --- Name: get_availability_zones(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_availability_zones() RETURNS SETOF systems.availability_zones - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "systems"."availability_zones" ORDER BY "zone"); - END; -$$; - - -ALTER FUNCTION api.get_availability_zones() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_availability_zones(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_availability_zones() IS 'Get all of the configured availability zones'; - - --- --- Name: get_current_user_groups(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_current_user_groups() RETURNS SETOF text - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY(SELECT "group" FROM "management"."group_members" WHERE "user" = api.get_current_user()); - END; -$$; - - -ALTER FUNCTION api.get_current_user_groups() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_current_user_groups(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_current_user_groups() IS 'Get the groups of the current user'; - - --- --- Name: get_current_user_level(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_current_user_level() RETURNS text - LANGUAGE plpgsql - AS $_$ - BEGIN - RETURN (SELECT "privilege" - FROM "user_privileges" - WHERE "allow" = TRUE - AND "privilege" ~* '^admin|program|user$'); - END; -$_$; - - -ALTER FUNCTION api.get_current_user_level() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_current_user_level(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_current_user_level() IS 'Get the level of the current session user'; - - --- --- Name: get_datacenters(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_datacenters() RETURNS SETOF systems.datacenters - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "systems"."datacenters" ORDER BY CASE WHEN "datacenter" = (SELECT api.get_site_configuration('DEFAULT_DATACENTER')) THEN 1 ELSE 2 END); - END; -$$; - - -ALTER FUNCTION api.get_datacenters() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_datacenters(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_datacenters() IS 'Get all of the available datacenters'; - - --- --- Name: get_default_renew_date(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_default_renew_date(input_system text) RETURNS date - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_system IS NULL THEN - RETURN date((('now'::text)::date + (api.get_site_configuration('DEFAULT_RENEW_INTERVAL'::text))::interval)); - ELSE - RETURN date(('now'::text)::date + (SELECT "renew_interval" FROM "management"."groups" - JOIN "systems"."systems" ON "systems"."systems"."group" = "management"."groups"."group" - WHERE "system_name" = input_system)); - END IF; - END; -$$; - - -ALTER FUNCTION api.get_default_renew_date(input_system text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_default_renew_date(input_system text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_default_renew_date(input_system text) IS 'Get the default renew date based on the configuration'; - - --- --- Name: get_dhcp_class(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcp_class(input_class text) RETURNS SETOF dhcp.classes - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_class IS NULL THEN - RETURN QUERY (SELECT * FROM "dhcp"."classes" ORDER BY "class"); - ELSE - RETURN QUERY (SELECT * FROM "dhcp"."classes" WHERE "class" = input_class ORDER BY "class"); - END IF; - END; -$$; - - -ALTER FUNCTION api.get_dhcp_class(input_class text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcp_class(input_class text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcp_class(input_class text) IS 'Get all DHCP class information for a specific class'; - - --- --- Name: get_dhcp_class_options(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcp_class_options(input_class text) RETURNS SETOF dhcp.class_options - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "dhcp"."class_options" WHERE "class" = input_class ORDER BY "option"); - END; -$$; - - -ALTER FUNCTION api.get_dhcp_class_options(input_class text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcp_class_options(input_class text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcp_class_options(input_class text) IS 'Get all DHCP class option data'; - - --- --- Name: get_dhcp_classes(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcp_classes() RETURNS SETOF dhcp.classes - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "dhcp"."classes" ORDER BY "class"); - END; -$$; - - -ALTER FUNCTION api.get_dhcp_classes() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcp_classes(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcp_classes() IS 'Get all DHCP class information'; - - -SET search_path = dhcp, pg_catalog; - --- --- Name: config_types; Type: TABLE; Schema: dhcp; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE config_types ( - config text NOT NULL, - comment text, - last_modifier text DEFAULT api.get_current_user() NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - family integer NOT NULL -); - - -ALTER TABLE dhcp.config_types OWNER TO starrs_admin; - --- --- Name: TABLE config_types; Type: COMMENT; Schema: dhcp; Owner: starrs_admin --- - -COMMENT ON TABLE config_types IS 'List of ways to configure your address'; - - -SET search_path = api, pg_catalog; - --- --- Name: get_dhcp_config_types(integer); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcp_config_types(input_family integer) RETURNS SETOF dhcp.config_types - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_family IS NULL THEN - RETURN QUERY (SELECT * FROM "dhcp"."config_types" ORDER BY CASE WHEN "config" = api.get_site_configuration('DEFAULT_CONFIG_TYPE') THEN 1 ELSE 2 END); - ELSE - RETURN QUERY (SELECT * FROM "dhcp"."config_types" WHERE "family" = input_family ORDER BY CASE WHEN "config" = api.get_site_configuration('DEFAULT_CONFIG_TYPE') THEN 1 ELSE 2 END); - END IF; - END; -$$; - - -ALTER FUNCTION api.get_dhcp_config_types(input_family integer) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcp_config_types(input_family integer); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcp_config_types(input_family integer) IS 'Get all DHCP config information'; - - --- --- Name: get_dhcp_global_options(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcp_global_options() RETURNS SETOF dhcp.global_options - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "dhcp"."global_options" ORDER BY "option"); - END; -$$; - - -ALTER FUNCTION api.get_dhcp_global_options() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcp_global_options(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcp_global_options() IS 'Get all DHCP global option data'; - - --- --- Name: get_dhcp_range_options(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcp_range_options(input_range text) RETURNS SETOF dhcp.range_options - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "dhcp"."range_options" WHERE "name" = input_range ORDER BY "option"); - END; -$$; - - -ALTER FUNCTION api.get_dhcp_range_options(input_range text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcp_range_options(input_range text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcp_range_options(input_range text) IS 'Get all DHCP range option data'; - - --- --- Name: get_dhcp_subnet_options(cidr); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcp_subnet_options(input_subnet cidr) RETURNS SETOF dhcp.subnet_options - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "dhcp"."subnet_options" WHERE "subnet" = input_subnet ORDER BY "option"); - END; -$$; - - -ALTER FUNCTION api.get_dhcp_subnet_options(input_subnet cidr) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcp_subnet_options(input_subnet cidr); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcp_subnet_options(input_subnet cidr) IS 'Get all DHCP subnet option data'; - - --- --- Name: get_dhcpd6_config(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcpd6_config() RETURNS text - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN (SELECT "value" FROM "management"."output" WHERE "file"='dhcpd6.conf' ORDER BY "timestamp" DESC LIMIT 1); - END; -$$; - - -ALTER FUNCTION api.get_dhcpd6_config() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcpd6_config(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcpd6_config() IS 'Get the latest DHCPD6 configuration file'; - - --- --- Name: get_dhcpd6_reverse_zones(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcpd6_reverse_zones() RETURNS SETOF dhcp.dhcpd_zones - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT DISTINCT api.get_reverse_domain("subnet") AS "zone","dns"."zones"."keyname","address" - FROM "ip"."subnets" - JOIN "dns"."zones" ON "dns"."zones"."zone" = "ip"."subnets"."zone" - JOIN "dns"."ns" ON "dns"."zones"."zone" = "dns"."ns"."zone" - WHERE "dns"."ns"."nameserver" IN (SELECT "nameserver" FROM "dns"."soa" WHERE "dns"."soa"."zone" = "ip"."subnets"."zone") - AND "dhcp_enable" = TRUE AND family("subnet") = 6 - ORDER BY api.get_reverse_domain("subnet"),"dns"."zones"."keyname","address"); - END; -$$; - - -ALTER FUNCTION api.get_dhcpd6_reverse_zones() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcpd6_reverse_zones(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcpd6_reverse_zones() IS 'Get all reverse zone info for dhcpd6'; - - --- --- Name: get_dhcpd6_static_hosts(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcpd6_static_hosts() RETURNS SETOF dhcp.dhcpd_static_hosts - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT "dns"."a"."hostname","dns"."a"."zone", - "systems"."interface_addresses"."mac","systems"."interface_addresses"."address","systems"."systems"."owner", - "systems"."interface_addresses"."class" - FROM "systems"."interface_addresses" - LEFT JOIN "dns"."a" ON "dns"."a"."address" = "systems"."interface_addresses"."address" - JOIN "systems"."interfaces" ON "systems"."interfaces"."mac" = "systems"."interface_addresses"."mac" - JOIN "systems"."systems" ON "systems"."systems"."system_name" = "systems"."interfaces"."system_name" - WHERE "systems"."interface_addresses"."config"='dhcpv6' - AND NOT "systems"."interface_addresses"."address" << (SELECT cidr(api.get_site_configuration('DYNAMIC_SUBNET'))) - AND ("dns"."a"."zone" IN (SELECT DISTINCT "zone" FROM "ip"."subnets" WHERE "dhcp_enable" IS TRUE ORDER BY "zone") - OR "dns"."a"."zone" IS NULL) ORDER BY "systems"."systems"."owner"); - END; -$$; - - -ALTER FUNCTION api.get_dhcpd6_static_hosts() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcpd6_static_hosts(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcpd6_static_hosts() IS 'Get all information for a host block of the dhcpd6.conf file'; - - --- --- Name: get_dhcpd_class_options(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcpd_class_options(input_class text) RETURNS SETOF dhcp.dhcpd_class_options - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT "option","value" FROM "dhcp"."class_options" WHERE "class" = input_class ORDER BY "option"); - END; -$$; - - -ALTER FUNCTION api.get_dhcpd_class_options(input_class text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcpd_class_options(input_class text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcpd_class_options(input_class text) IS 'Get class options for the dhcpd.conf file'; - - --- --- Name: get_dhcpd_classes(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcpd_classes() RETURNS SETOF dhcp.dhcpd_classes - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT "class","comment" FROM "dhcp"."classes" ORDER BY "class"); - END; -$$; - - -ALTER FUNCTION api.get_dhcpd_classes() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcpd_classes(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcpd_classes() IS 'Get class information for the dhcpd.conf file'; - - --- --- Name: get_dhcpd_config(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcpd_config() RETURNS text - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN (SELECT "value" FROM "management"."output" WHERE "file"='dhcpd.conf' ORDER BY "timestamp" DESC LIMIT 1); - END; -$$; - - -ALTER FUNCTION api.get_dhcpd_config() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcpd_config(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcpd_config() IS 'Get the latest DHCPD configuration file'; - - --- --- Name: get_dhcpd_dns_keys(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcpd_dns_keys() RETURNS SETOF dhcp.dhcpd_dns_keys - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission denied on get_dhcpd_dns_keys: You are not admin.'; - END IF; - - -- Return data - RETURN QUERY (SELECT DISTINCT "dns"."zones"."keyname","dns"."keys"."key","dns"."keys"."enctype" - FROM "ip"."subnets" - JOIN "dns"."zones" ON "dns"."zones"."zone" = "ip"."subnets"."zone" - JOIN "dns"."keys" ON "dns"."keys"."keyname" = "dns"."zones"."keyname" - WHERE "dhcp_enable" = TRUE - ORDER BY "dns"."zones"."keyname","dns"."keys"."key","dns"."keys"."enctype"); - END; -$$; - - -ALTER FUNCTION api.get_dhcpd_dns_keys() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcpd_dns_keys(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcpd_dns_keys() IS 'Get all of the dns keys for dhcpd'; - - --- --- Name: get_dhcpd_dynamic_hosts(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcpd_dynamic_hosts() RETURNS SETOF dhcp.dhcpd_dynamic_hosts - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT "dns"."a"."hostname","dns"."a"."zone", - "systems"."interface_addresses"."mac","systems"."systems"."owner","systems"."interface_addresses"."class" - FROM "systems"."interface_addresses" - LEFT JOIN "dns"."a" ON "dns"."a"."address" = "systems"."interface_addresses"."address" - JOIN "systems"."interfaces" ON "systems"."interfaces"."mac" = "systems"."interface_addresses"."mac" - JOIN "systems"."systems" ON "systems"."systems"."system_name" = "systems"."interfaces"."system_name" - WHERE "systems"."interface_addresses"."config"='dhcp' - AND "systems"."interface_addresses"."address" << (SELECT cidr(api.get_site_configuration('DYNAMIC_SUBNET'))) - AND ("dns"."a"."zone" IN (SELECT DISTINCT "zone" FROM "ip"."subnets" WHERE "dhcp_enable" IS TRUE ORDER BY "zone") - OR "dns"."a"."zone" IS NULL) ORDER BY "systems"."systems"."owner"); - END; -$$; - - -ALTER FUNCTION api.get_dhcpd_dynamic_hosts() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcpd_dynamic_hosts(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcpd_dynamic_hosts() IS 'Get all information for a host block of the dhcpd.conf file'; - - --- --- Name: get_dhcpd_forward_zones(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcpd_forward_zones() RETURNS SETOF dhcp.dhcpd_zones - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT DISTINCT "ip"."subnets"."zone","dns"."zones"."keyname","address" - FROM "ip"."subnets" - JOIN "dns"."zones" ON "dns"."zones"."zone" = "ip"."subnets"."zone" - JOIN "dns"."ns" ON "dns"."zones"."zone" = "dns"."ns"."zone" - WHERE "dns"."ns"."nameserver" IN (SELECT "nameserver" FROM "dns"."soa" WHERE "dns"."soa"."zone" = "ip"."subnets"."zone") - ORDER BY "ip"."subnets"."zone"); - END; -$$; - - -ALTER FUNCTION api.get_dhcpd_forward_zones() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcpd_forward_zones(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcpd_forward_zones() IS 'Get all forward zone info for dhcpd'; - - --- --- Name: get_dhcpd_global_options(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcpd_global_options() RETURNS SETOF dhcp.dhcpd_global_options - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT "option","value" FROM "dhcp"."global_options" ORDER BY CASE WHEN "option" = 'option space' THEN 1 ELSE 2 END); - END; -$$; - - -ALTER FUNCTION api.get_dhcpd_global_options() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcpd_global_options(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcpd_global_options() IS 'Get all of the global DHCPD config directives'; - - --- --- Name: get_dhcpd_range_options(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcpd_range_options(input_range text) RETURNS SETOF dhcp.dhcpd_range_options - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT "option","value" FROM "dhcp"."range_options" WHERE "name" = input_range ORDER BY "option"); - END; -$$; - - -ALTER FUNCTION api.get_dhcpd_range_options(input_range text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcpd_range_options(input_range text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcpd_range_options(input_range text) IS 'Get all range options for dhcpd.conf'; - - --- --- Name: get_dhcpd_reverse_zones(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcpd_reverse_zones() RETURNS SETOF dhcp.dhcpd_zones - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT DISTINCT api.get_reverse_domain("subnet") AS "zone","dns"."zones"."keyname","address" - FROM "ip"."subnets" - JOIN "dns"."zones" ON "dns"."zones"."zone" = "ip"."subnets"."zone" - JOIN "dns"."ns" ON "dns"."zones"."zone" = "dns"."ns"."zone" - WHERE "dns"."ns"."nameserver" IN (SELECT "nameserver" FROM "dns"."soa" WHERE "dns"."soa"."zone" = "ip"."subnets"."zone") - AND "dhcp_enable" = TRUE AND family("subnet") = 4 - ORDER BY api.get_reverse_domain("subnet"),"dns"."zones"."keyname","address"); - END; -$$; - - -ALTER FUNCTION api.get_dhcpd_reverse_zones() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcpd_reverse_zones(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcpd_reverse_zones() IS 'Get all reverse zone info for dhcpd'; - - --- --- Name: get_dhcpd_shared_network_subnets(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcpd_shared_network_subnets(input_name text) RETURNS SETOF cidr - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT "subnet" FROM "network"."vlans" JOIN "ip"."subnets" ON "network"."vlans"."vlan" = "ip"."subnets"."vlan" WHERE "network"."vlans"."name" = input_name AND "dhcp_enable" IS TRUE); - END; -$$; - - -ALTER FUNCTION api.get_dhcpd_shared_network_subnets(input_name text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcpd_shared_network_subnets(input_name text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcpd_shared_network_subnets(input_name text) IS 'Get the subnets for DHCPD'; - - --- --- Name: get_dhcpd_shared_networks(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcpd_shared_networks() RETURNS SETOF text - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT "name" FROM "network"."vlans" WHERE "datacenter" = api.get_site_configuration('DEFAULT_DATACENTER') ORDER BY "name"); - END; -$$; - - -ALTER FUNCTION api.get_dhcpd_shared_networks() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcpd_shared_networks(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcpd_shared_networks() IS 'Get DHCPD shared networks'; - - --- --- Name: get_dhcpd_static_hosts(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcpd_static_hosts() RETURNS SETOF dhcp.dhcpd_static_hosts - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT "dns"."a"."hostname","dns"."a"."zone", - "systems"."interface_addresses"."mac","systems"."interface_addresses"."address","systems"."systems"."owner", - "systems"."interface_addresses"."class" - FROM "systems"."interface_addresses" - LEFT JOIN "dns"."a" ON "dns"."a"."address" = "systems"."interface_addresses"."address" - JOIN "systems"."interfaces" ON "systems"."interfaces"."mac" = "systems"."interface_addresses"."mac" - JOIN "systems"."systems" ON "systems"."systems"."system_name" = "systems"."interfaces"."system_name" - WHERE "systems"."interface_addresses"."config"='dhcp' - AND NOT "systems"."interface_addresses"."address" << (SELECT cidr(api.get_site_configuration('DYNAMIC_SUBNET'))) - AND ("dns"."a"."zone" IN (SELECT DISTINCT "zone" FROM "ip"."subnets" WHERE "dhcp_enable" IS TRUE ORDER BY "zone") - OR "dns"."a"."zone" IS NULL) ORDER BY "systems"."systems"."owner"); - END; -$$; - - -ALTER FUNCTION api.get_dhcpd_static_hosts() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcpd_static_hosts(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcpd_static_hosts() IS 'Get all information for a host block of the dhcpd.conf file'; - - --- --- Name: get_dhcpd_subnet_options(cidr); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcpd_subnet_options(input_subnet cidr) RETURNS SETOF dhcp.dhcpd_subnet_options - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT "option","value" FROM "dhcp"."subnet_options" WHERE "subnet" = input_subnet ORDER BY "option"); - END; -$$; - - -ALTER FUNCTION api.get_dhcpd_subnet_options(input_subnet cidr) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcpd_subnet_options(input_subnet cidr); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcpd_subnet_options(input_subnet cidr) IS 'Get all subnet options for dhcpd.conf'; - - --- --- Name: get_dhcpd_subnet_ranges(cidr); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcpd_subnet_ranges(input_subnet cidr) RETURNS SETOF dhcp.dhcpd_subnet_ranges - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT "name","first_ip","last_ip","class" FROM "ip"."ranges" WHERE "subnet" = input_subnet AND "use" = 'ROAM' AND family("subnet") = 4 ORDER BY "subnet"); - END; -$$; - - -ALTER FUNCTION api.get_dhcpd_subnet_ranges(input_subnet cidr) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcpd_subnet_ranges(input_subnet cidr); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcpd_subnet_ranges(input_subnet cidr) IS 'Get a list of all dynamic ranges in a subnet'; - - --- --- Name: get_dhcpd_subnets(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dhcpd_subnets() RETURNS SETOF cidr - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT "subnet" FROM "ip"."subnets" WHERE "dhcp_enable" = TRUE AND family("subnet") = 4 ORDER BY "subnet"); - END; -$$; - - -ALTER FUNCTION api.get_dhcpd_subnets() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dhcpd_subnets(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dhcpd_subnets() IS 'Get a list of all DHCP enabled subnets for DHCPD'; - - --- --- Name: get_dns_a(inet, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dns_a(input_address inet, input_zone text) RETURNS SETOF dns.a - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_zone IS NULL THEN - IF input_address IS NULL THEN - RETURN QUERY (SELECT * FROM "dns"."a" ORDER BY "address"); - ELSE - RETURN QUERY (SELECT * FROM "dns"."a" WHERE "address" = input_address ORDER BY "zone" ASC); - END IF; - ELSE - IF input_address IS NULL THEN - RETURN QUERY (SELECT * FROM "dns"."a" ORDER BY "address"); - ELSE - RETURN QUERY (SELECT * FROM "dns"."a" WHERE "address" = input_address AND "zone" = input_zone ORDER BY "zone"); - END IF; - END IF; - END; -$$; - - -ALTER FUNCTION api.get_dns_a(input_address inet, input_zone text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dns_a(input_address inet, input_zone text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dns_a(input_address inet, input_zone text) IS 'Get all DNS address records for an address'; - - --- --- Name: get_dns_cname(inet); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dns_cname(input_address inet) RETURNS SETOF dns.cname - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_address IS NULL THEN - RETURN QUERY (SELECT * FROM "dns"."cname" ORDER BY "alias"); - ELSE - RETURN QUERY (SELECT * FROM "dns"."cname" WHERE "address" = input_address ORDER BY "alias" ASC); - END IF; - END; -$$; - - -ALTER FUNCTION api.get_dns_cname(input_address inet) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dns_cname(input_address inet); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dns_cname(input_address inet) IS 'Get all DNS CNAME records for an address'; - - --- --- Name: get_dns_key(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dns_key(input_keyname text) RETURNS SETOF dns.keys - LANGUAGE plpgsql - AS $$ - BEGIN - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF (SELECT "owner" FROM "dns"."keys" WHERE "keyname" = input_keyname) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission to get DNS key denied: You are not admin or owner'; - END IF; - END IF; - RETURN QUERY (SELECT * FROM "dns"."keys" WHERE "keyname" = input_keyname); - END; -$$; - - -ALTER FUNCTION api.get_dns_key(input_keyname text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dns_key(input_keyname text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dns_key(input_keyname text) IS 'Get DNS key data'; - - --- --- Name: get_dns_keys(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dns_keys(input_username text) RETURNS SETOF dns.keys - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_username IS NULL THEN - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission to get DNS keys denied: You are not admin'; - END IF; - RETURN QUERY (SELECT * FROM "dns"."keys" ORDER BY "keyname"); - ELSE - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF input_username != api.get_current_user() THEN - RAISE EXCEPTION 'Permission to get DNS keys denied: You are not admin or owner'; - END IF; - END IF; - RETURN QUERY (SELECT * FROM "dns"."keys" WHERE "owner" = input_username ORDER BY "keyname" ASC); - END IF; - END; -$$; - - -ALTER FUNCTION api.get_dns_keys(input_username text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dns_keys(input_username text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dns_keys(input_username text) IS 'Get DNS key data'; - - --- --- Name: get_dns_mx(inet); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dns_mx(input_address inet) RETURNS SETOF dns.mx - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_address IS NULL THEN - RETURN QUERY (SELECT * FROM "dns"."mx" ORDER BY "preference"); - ELSE - RETURN QUERY (SELECT * FROM "dns"."mx" WHERE "address" = input_address ORDER BY "preference"); - END IF; - END; -$$; - - -ALTER FUNCTION api.get_dns_mx(input_address inet) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dns_mx(input_address inet); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dns_mx(input_address inet) IS 'Get all data pertanent to DNS MX records for an address'; - - --- --- Name: get_dns_ns(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dns_ns(input_zone text) RETURNS SETOF dns.ns - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_zone IS NULL THEN - RETURN QUERY (SELECT * FROM "dns"."ns" ORDER BY "nameserver"); - ELSE - RETURN QUERY (SELECT * FROM "dns"."ns" WHERE "zone" = input_zone ORDER BY "nameserver"); - END IF; - END; -$$; - - -ALTER FUNCTION api.get_dns_ns(input_zone text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dns_ns(input_zone text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dns_ns(input_zone text) IS 'Get all DNS NS records for a zone'; - - --- --- Name: get_dns_soa(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dns_soa(input_zone text) RETURNS SETOF dns.soa - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_zone IS NULL THEN - RETURN QUERY (SELECT * FROM "dns"."soa" ORDER BY "zone"); - ELSE - RETURN QUERY (SELECT * FROM "dns"."soa" WHERE "dns"."soa"."zone" = input_zone); - END IF; - END; -$$; - - -ALTER FUNCTION api.get_dns_soa(input_zone text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dns_soa(input_zone text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dns_soa(input_zone text) IS 'Get the SOA record of a DNS zone'; - - --- --- Name: get_dns_srv(inet); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dns_srv(input_address inet) RETURNS SETOF dns.srv - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_address IS NULL THEN - RETURN QUERY (SELECT * FROM "dns"."srv" ORDER BY "alias"); - ELSE - RETURN QUERY (SELECT * FROM "dns"."srv" WHERE "address" = input_address ORDER BY "alias" ASC); - END IF; - END; -$$; - - -ALTER FUNCTION api.get_dns_srv(input_address inet) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dns_srv(input_address inet); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dns_srv(input_address inet) IS 'Get all DNS SRV records for an address'; - - --- --- Name: get_dns_txt(inet); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dns_txt(input_address inet) RETURNS SETOF dns.txt - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_address IS NULL THEN - RETURN QUERY (SELECT * FROM "dns"."txt" ORDER BY "text"); - ELSE - RETURN QUERY (SELECT * FROM "dns"."txt" WHERE "address" = input_address ORDER BY "text"); - END IF; - END; -$$; - - -ALTER FUNCTION api.get_dns_txt(input_address inet) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dns_txt(input_address inet); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dns_txt(input_address inet) IS 'Get all DNS TXT records for an address'; - - --- --- Name: get_dns_zone(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dns_zone(input_zone text) RETURNS SETOF dns.zones - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_zone IS NULL THEN - RETURN QUERY(SELECT * FROM "dns"."zones" ORDER BY "zone"); - ELSE - RETURN QUERY(SELECT * FROM "dns"."zones" WHERE "zone" = input_zone ORDER BY "zone"); - END IF; - END; -$$; - - -ALTER FUNCTION api.get_dns_zone(input_zone text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dns_zone(input_zone text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dns_zone(input_zone text) IS 'Get detailed dns zone information'; - - --- --- Name: get_dns_zone_a(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dns_zone_a(input_zone text) RETURNS SETOF dns.zone_a - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_zone IS NULL THEN - RETURN QUERY (SELECT * FROM "dns"."zone_a" ORDER BY "address"); - ELSE - RETURN QUERY (SELECT * FROM "dns"."zone_a" WHERE "zone" = input_zone ORDER BY "address"); - END IF; - END; -$$; - - -ALTER FUNCTION api.get_dns_zone_a(input_zone text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dns_zone_a(input_zone text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dns_zone_a(input_zone text) IS 'Get all DNS address records for a zone'; - - --- --- Name: get_dns_zone_txt(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dns_zone_txt(input_zone text) RETURNS SETOF dns.zone_txt - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_zone IS NULL THEN - RETURN QUERY (SELECT * FROM "dns"."zone_txt" ORDER BY "hostname"); - ELSE - RETURN QUERY (SELECT * FROM "dns"."zone_txt" WHERE "zone" = input_zone ORDER BY "hostname" ASC); - END IF; - END; -$$; - - -ALTER FUNCTION api.get_dns_zone_txt(input_zone text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dns_zone_txt(input_zone text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dns_zone_txt(input_zone text) IS 'Get all DNS TXT records specifically for a zone'; - - --- --- Name: get_dns_zones(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_dns_zones(input_username text) RETURNS SETOF dns.zones - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_username IS NULL THEN - RETURN QUERY(SELECT * FROM "dns"."zones" ORDER BY CASE WHEN "zone" = (SELECT api.get_site_configuration('DNS_DEFAULT_ZONE')) THEN 1 ELSE 2 END, "forward" DESC, "zone" ASC); - ELSE - RETURN QUERY(SELECT * FROM "dns"."zones" WHERE "shared" = TRUE OR "owner" = input_username ORDER BY CASE WHEN "zone" = (SELECT api.get_site_configuration('DNS_DEFAULT_ZONE')) THEN 1 ELSE 2 END, "forward" DESC, "zone" ASC); - END IF; - END; -$$; - - -ALTER FUNCTION api.get_dns_zones(input_username text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_dns_zones(input_username text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_dns_zones(input_username text) IS 'Get the available zones to a user'; - - --- --- Name: get_domain_state(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_domain_state(input_system text) RETURNS text - LANGUAGE plpgsql - AS $$ - DECLARE - HostData RECORD; - BEGIN - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF (SELECT "owner" FROM "systems"."system" WHERE "system_name" = input_system) THEN - RAISE EXCEPTION 'Permission denied: Not VM owner'; - END IF; - END IF; - - SELECT * INTO HostData FROM "libvirt"."hosts" WHERE "system_name" = (SELECT "host_name" FROM "libvirt"."domains" WHERE "domain_name" = input_system); - - RETURN api.get_libvirt_domain_state(HostData.uri, HostData.password, input_system); - END; -$$; - - -ALTER FUNCTION api.get_domain_state(input_system text) OWNER TO starrs_admin; - --- --- Name: get_function_counts(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_function_counts(input_schema text) RETURNS TABLE(function text, calls integer) - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY( - SELECT "information_schema"."routines"."routine_name"::text,"pg_stat_user_functions"."calls"::integer - FROM "information_schema"."routines" - LEFT JOIN "pg_stat_user_functions" ON "pg_stat_user_functions"."funcname" = "information_schema"."routines"."routine_name" - WHERE "information_schema"."routines"."routine_schema" = input_schema - ); - END; -$$; - - -ALTER FUNCTION api.get_function_counts(input_schema text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_function_counts(input_schema text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_function_counts(input_schema text) IS 'Get statistics on number of calls to each function in a schema'; - - --- --- Name: get_group_admins(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_group_admins(input_group text) RETURNS SETOF text - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY(SELECT "user" FROM "management"."group_members" WHERE "group" = input_group AND "privilege" = 'ADMIN'); - END; -$$; - - -ALTER FUNCTION api.get_group_admins(input_group text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_group_admins(input_group text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_group_admins(input_group text) IS 'Get a list of all admins for a group'; - - --- --- Name: get_group_members(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_group_members(input_group text) RETURNS SETOF management.group_members - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "management"."group_members" WHERE "group" = input_group ORDER BY "user"); - END; -$$; - - -ALTER FUNCTION api.get_group_members(input_group text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_group_members(input_group text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_group_members(input_group text) IS 'Get all members of a group'; - - --- --- Name: get_group_ranges(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_group_ranges(input_group text) RETURNS SETOF ip.ranges - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "ip"."ranges" WHERE "name" IN (SELECT "range_name" FROM "ip"."range_groups" WHERE "group_name" = input_group) ORDER BY "name"); - END; -$$; - - -ALTER FUNCTION api.get_group_ranges(input_group text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_group_ranges(input_group text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_group_ranges(input_group text) IS 'Get group range information'; - - --- --- Name: get_group_settings(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_group_settings(input_group text) RETURNS SETOF management.group_settings - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission denied. Only admins can view group provider settings'; - END IF; - - -- return - RETURN QUERY (SELECT * FROM "management"."group_settings" WHERE "group" = input_group); - END; -$$; - - -ALTER FUNCTION api.get_group_settings(input_group text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_group_settings(input_group text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_group_settings(input_group text) IS 'Get group settings'; - - --- --- Name: get_groups(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_groups() RETURNS SETOF management.groups - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "management"."groups" ORDER BY "group"); - END; -$$; - - -ALTER FUNCTION api.get_groups() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_groups(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_groups() IS 'Get all of the configured groups'; - - --- --- Name: get_host_domain(text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_host_domain(input_system text, input_domain text) RETURNS SETOF libvirt.domains - LANGUAGE plpgsql - AS $$ - DECLARE - HostData RECORD; - BEGIN - SELECT * INTO HostData FROM "libvirt"."hosts" WHERE "system_name" = input_system; - RETURN QUERY (SELECT input_system AS "host_name","domain","state","definition",localtimestamp(0) AS "date_created", localtimestamp(0) AS "date_modified", api.get_current_user() AS "last_modifier" FROM api.get_libvirt_domain(HostData.uri, HostData.password, input_domain)); - END; -$$; - - -ALTER FUNCTION api.get_host_domain(input_system text, input_domain text) OWNER TO starrs_admin; - --- --- Name: get_host_domains(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_host_domains(input_system text) RETURNS SETOF libvirt.domains - LANGUAGE plpgsql - AS $$ - DECLARE - HostData RECORD; - BEGIN - SELECT * INTO HostData FROM "libvirt"."hosts" WHERE "system_name" = input_system; - RETURN QUERY (SELECT input_system AS "host_name","domain","state","definition",localtimestamp(0) AS "date_created", localtimestamp(0) AS "date_modified", api.get_current_user() AS "last_modifier" FROM api.get_libvirt_domains(HostData.uri, HostData.password)); - END; -$$; - - -ALTER FUNCTION api.get_host_domains(input_system text) OWNER TO starrs_admin; - --- --- Name: get_hosts(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_hosts(input_user text) RETURNS SETOF libvirt.hosts - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_user IS NULL THEN - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Only admins can view all VM hosts'; - END IF; - RETURN QUERY (SELECT * FROM "libvirt"."hosts" ORDER BY "system_name"); - ELSE - IF api.get_current_user_level() !~* 'ADMIN' THEN - RETURN QUERY (SELECT * FROM "libvirt"."hosts" WHERE api.get_system_owner("system_name") = input_user ORDER BY "system_name"); - ELSE - RETURN QUERY (SELECT * FROM "libvirt"."hosts" ORDER BY "system_name"); - END IF; - END IF; - END; -$$; - - -ALTER FUNCTION api.get_hosts(input_user text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_hosts(input_user text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_hosts(input_user text) IS 'Get all VM hosts'; - - --- --- Name: get_interface_address_owner(inet); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_interface_address_owner(input_address inet) RETURNS text - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN (SELECT "owner" FROM systems.interface_addresses - JOIN systems.interfaces on systems.interface_addresses.mac = systems.interfaces.mac - JOIN systems.systems on systems.interfaces.system_name = systems.systems.system_name - WHERE "address" = input_address); - END; -$$; - - -ALTER FUNCTION api.get_interface_address_owner(input_address inet) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_interface_address_owner(input_address inet); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_interface_address_owner(input_address inet) IS 'Get the owner of an interface address'; - - --- --- Name: get_interface_address_system(inet); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_interface_address_system(input_address inet) RETURNS text - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN (SELECT "system_name" FROM "systems"."interface_addresses" - JOIN "systems"."interfaces" ON "systems"."interface_addresses"."mac" = "systems"."interfaces"."mac" - WHERE "address" = input_address); - END; -$$; - - -ALTER FUNCTION api.get_interface_address_system(input_address inet) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_interface_address_system(input_address inet); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_interface_address_system(input_address inet) IS 'Get the name of the system to which the given address is assigned'; - - --- --- Name: get_interface_owner(macaddr); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_interface_owner(input_mac macaddr) RETURNS text - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN (SELECT "owner" FROM "systems"."interfaces" - JOIN "systems"."systems" ON "systems"."interfaces"."system_name" = "systems"."systems"."system_name" - WHERE "mac" = input_mac); - END; -$$; - - -ALTER FUNCTION api.get_interface_owner(input_mac macaddr) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_interface_owner(input_mac macaddr); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_interface_owner(input_mac macaddr) IS 'Get the owner of the system that contains the mac address'; - - -SET search_path = network, pg_catalog; - --- --- Name: cam_cache; Type: TABLE; Schema: network; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE cam_cache ( - system_name text NOT NULL, - mac macaddr NOT NULL, - ifindex integer NOT NULL, - vlan integer NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE network.cam_cache OWNER TO starrs_admin; - --- --- Name: TABLE cam_cache; Type: COMMENT; Schema: network; Owner: starrs_admin --- - -COMMENT ON TABLE cam_cache IS 'Cache switch data for port mappings'; - - -SET search_path = api, pg_catalog; - --- --- Name: get_interface_switchports(macaddr); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_interface_switchports(input_mac macaddr) RETURNS SETOF network.cam_cache - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "network"."cam_cache" WHERE "mac" = input_mac); - END; -$$; - - -ALTER FUNCTION api.get_interface_switchports(input_mac macaddr) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_interface_switchports(input_mac macaddr); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_interface_switchports(input_mac macaddr) IS 'Get all the cam cache entries for MAC'; - - --- --- Name: get_interface_system(macaddr); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_interface_system(input_mac macaddr) RETURNS text - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN (SELECT "system_name" FROM "systems"."interfaces" WHERE "mac" = input_mac); - END; -$$; - - -ALTER FUNCTION api.get_interface_system(input_mac macaddr) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_interface_system(input_mac macaddr); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_interface_system(input_mac macaddr) IS 'Get the system name that a mac address is on'; - - --- --- Name: get_ip_mask_bits(inet); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_ip_mask_bits(input_subnet inet) RETURNS integer - LANGUAGE plpgsql - AS $$ - DECLARE - t1 TEXT; - t2 TEXT; - t3 TEXT; - t4 TEXT; - i BIGINT; - n INTEGER; - BEGIN - IF family(input_subnet) != 4 THEN - RAISE EXCEPTION 'Can only get mask bits of an IPv4 address'; - END IF; - - t1 := SPLIT_PART(HOST(input_subnet), '.',1); - t2 := SPLIT_PART(HOST(input_subnet), '.',2); - t3 := SPLIT_PART(HOST(input_subnet), '.',3); - t4 := SPLIT_PART(HOST(input_subnet), '.',4); - i := (t1::BIGINT << 24) + (t2::BIGINT << 16) + - (t3::BIGINT << 8) + t4::BIGINT; - n := (32-log(2, 4294967296 - i ))::integer; - - RETURN n; - END; -$$; - - -ALTER FUNCTION api.get_ip_mask_bits(input_subnet inet) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_ip_mask_bits(input_subnet inet); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_ip_mask_bits(input_subnet inet) IS 'Get the number of bits in a subnet mask'; - - --- --- Name: get_ip_range_total(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_ip_range_total(input_range text) RETURNS integer - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN (SELECT COUNT(api.get_address_range("address")) - FROM "ip"."addresses" - WHERE api.get_address_range("address") ~* input_range); - END; -$$; - - -ALTER FUNCTION api.get_ip_range_total(input_range text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_ip_range_total(input_range text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_ip_range_total(input_range text) IS 'Get the number of possible addresses in a particiular range'; - - --- --- Name: get_ip_range_uses(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_ip_range_uses() RETURNS SETOF text - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT text("use") FROM "ip"."range_uses"); - END; -$$; - - -ALTER FUNCTION api.get_ip_range_uses() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_ip_range_uses(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_ip_range_uses() IS 'Get a list of all use codes'; - - --- --- Name: get_ip_ranges(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_ip_ranges() RETURNS SETOF ip.ranges - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "ip"."ranges" ORDER BY "first_ip"); - END; -$$; - - -ALTER FUNCTION api.get_ip_ranges() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_ip_ranges(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_ip_ranges() IS 'Get all configured IP ranges'; - - --- --- Name: get_ip_subnets(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_ip_subnets(input_username text) RETURNS SETOF ip.subnets - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_username IS NULL THEN - RETURN QUERY (SELECT * FROM "ip"."subnets" ORDER BY "subnet"); - ELSE - RETURN QUERY (SELECT * FROM "ip"."subnets" WHERE "owner" = input_username ORDER BY "subnet"); - END IF; - END; -$$; - - -ALTER FUNCTION api.get_ip_subnets(input_username text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_ip_subnets(input_username text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_ip_subnets(input_username text) IS 'Get all IP subnet data'; - - --- --- Name: get_ldap_group_members(text, text, text, text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION get_ldap_group_members(text, text, text, text) RETURNS SETOF text - LANGUAGE plperlu - AS $_X$ - use strict; - use warnings; - use Net::LDAP; - - # Get the credentials - my $hostname = $_[0] or die "Need to give a hostname"; - my $id= $_[1] or die "Need to give an ID"; - my $binddn = $_[2] or die "Need to give a username"; - my $password = $_[3] or die "Need to give a password"; - - my $srv = Net::LDAP->new ($hostname) or die "Could not connect to LDAP server ($hostname)\n"; - my $mesg = $srv->bind($binddn,password=>$password) or die "Could not bind to LDAP server"; - - my @members; - - my @dnparts = split(/,/, $id); - my $filter = shift(@dnparts); - my $base = join(",",@dnparts); - - - $mesg = $srv->search(filter=>"($filter)",base=>$base); - foreach my $entry ($mesg->entries) { - my @vals = $entry->get_value('member'); - foreach my $val (@vals) { - $val =~ s/^uid=(.*?),(.*?)$/$1/; - push(@members, $val); - } - } - - return \@members; - -$_X$; - - -ALTER FUNCTION api.get_ldap_group_members(text, text, text, text) OWNER TO postgres; - --- --- Name: get_ldap_user_level(text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION get_ldap_user_level(text) RETURNS text - LANGUAGE plperlu - AS $_X$ - use strict; - use warnings; - use Net::LDAP; - - # Get the current authenticated username - my $username = $_[0] or die "Need to give a username"; - - # If this is the installer, we dont need to query the server - if ($username eq "root") - { - return "ADMIN"; - } - - # Get LDAP connection information - my $host = spi_exec_query("SELECT api.get_site_configuration('LDAP_HOST')")->{rows}[0]->{"get_site_configuration"}; - my $binddn = spi_exec_query("SELECT api.get_site_configuration('LDAP_BINDDN')")->{rows}[0]->{"get_site_configuration"}; - my $password = spi_exec_query("SELECT api.get_site_configuration('LDAP_PASSWORD')")->{rows}[0]->{"get_site_configuration"}; - my $admin_filter = spi_exec_query("SELECT api.get_site_configuration('LDAP_ADMIN_FILTER')")->{rows}[0]->{"get_site_configuration"}; - my $admin_basedn = spi_exec_query("SELECT api.get_site_configuration('LDAP_ADMIN_BASEDN')")->{rows}[0]->{"get_site_configuration"}; - my $program_filter = spi_exec_query("SELECT api.get_site_configuration('LDAP_PROGRAM_FILTER')")->{rows}[0]->{"get_site_configuration"}; - my $program_basedn = spi_exec_query("SELECT api.get_site_configuration('LDAP_PROGRAM_BASEDN')")->{rows}[0]->{"get_site_configuration"}; - my $user_filter = spi_exec_query("SELECT api.get_site_configuration('LDAP_USER_FILTER')")->{rows}[0]->{"get_site_configuration"}; - my $user_basedn = spi_exec_query("SELECT api.get_site_configuration('LDAP_USER_BASEDN')")->{rows}[0]->{"get_site_configuration"}; - - # The lowest status. Build from here. - my $status = "NONE"; - - # Bind to the LDAP server - my $srv = Net::LDAP->new ($host) or die "Could not connect to LDAP server ($host)\n"; - my $mesg = $srv->bind($binddn,password=>$password) or die "Could not bind to LDAP server at $host\n"; - - # Go through the directory and see if this user is a user account - $mesg = $srv->search(filter=>"($user_filter=$username)",base=>$user_basedn,attrs=>[$user_filter]); - foreach my $entry ($mesg->entries) - { - my @users = $entry->get_value($user_filter); - foreach my $user (@users) - { - $user =~ s/^uid=(.*?)\,(.*?)$/$1/; - if ($user eq $username) - { - $status = "USER"; - } - } - } - - # Go through the directory and see if this user is a program account - $mesg = $srv->search(filter=>"($program_filter=$username)",base=>$program_basedn,attrs=>[$program_filter]); - foreach my $entry ($mesg->entries) - { - my @programs = $entry->get_value($program_filter); - foreach my $program (@programs) - { - if ($program eq $username) - { - $status = "PROGRAM"; - } - } - } - - # Go through the directory and see if this user is an admin - # Fancy hacks to allow for less hardcoding of attributes - my $admin_filter_atr = $admin_filter; - $admin_filter_atr =~ s/^(.*?)[^a-zA-Z0-9]+$/$1/; - $mesg = $srv->search(filter=>"($admin_filter)",base=>$admin_basedn,attrs=>[$admin_filter_atr]); - foreach my $entry ($mesg->entries) - { - my @admins = $entry->get_value($admin_filter_atr); - foreach my $admin (@admins) - { - $admin =~ s/^uid=(.*?)\,(.*?)$/$1/; - if ($admin eq $username) - { - $status = "ADMIN"; - } - } - } - - # Unbind from the LDAP server - $srv->unbind; - - # Done - return $status; - -# if($_[0] eq 'root') -# { -# return "ADMIN" -# } -# else -# { -# return "USER"; -# } -$_X$; - - -ALTER FUNCTION api.get_ldap_user_level(text) OWNER TO postgres; - --- --- Name: FUNCTION get_ldap_user_level(text); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION get_ldap_user_level(text) IS 'Get the level of access for the authenticated user'; - - --- --- Name: get_libvirt_domain(text, text, text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION get_libvirt_domain(sysuri text, syspassword text, domainname text) RETURNS libvirt.domain_data - LANGUAGE plpython2u - AS $$ - #!/usr/bin/python - - import libvirt - import sys - - def request_credentials(credentials, data): - for credential in credentials: - if credential[0] == libvirt.VIR_CRED_AUTHNAME: - #credential[4] = sysuser - return 0 - elif credential[0] == libvirt.VIR_CRED_NOECHOPROMPT: - credential[4] = syspassword - else: - return -1 - - return 0 - - auth = [[libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_NOECHOPROMPT], request_credentials, None] - if syspassword == None: - conn = libvirt.open(sysuri) - else: - conn = libvirt.openAuth(sysuri, auth, 0) - - if conn == None: - sys.exit("Unable to connect") - - state_names = { libvirt.VIR_DOMAIN_RUNNING : "running", - libvirt.VIR_DOMAIN_BLOCKED : "idle", - libvirt.VIR_DOMAIN_PAUSED : "paused", - libvirt.VIR_DOMAIN_SHUTDOWN : "in shutdown", - libvirt.VIR_DOMAIN_SHUTOFF : "shut off", - libvirt.VIR_DOMAIN_CRASHED : "crashed", - libvirt.VIR_DOMAIN_NOSTATE : "no state" } - - domain = conn.lookupByName(domainname) - return ([domain.name(), state_names[domain.info()[0]], domain.XMLDesc(0)]) -$$; - - -ALTER FUNCTION api.get_libvirt_domain(sysuri text, syspassword text, domainname text) OWNER TO postgres; - --- --- Name: get_libvirt_domain_state(text, text, text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION get_libvirt_domain_state(sysuri text, syspassword text, domain text) RETURNS text - LANGUAGE plpython2u - AS $$ - #!/usr/bin/python - - import libvirt - import sys - - def request_credentials(credentials, data): - for credential in credentials: - if credential[0] == libvirt.VIR_CRED_AUTHNAME: - return 0 - elif credential[0] == libvirt.VIR_CRED_NOECHOPROMPT: - credential[4] = syspassword - else: - return -1 - - return 0 - - auth = [[libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_NOECHOPROMPT], request_credentials, None] - conn = libvirt.openAuth(sysuri, auth, 0) - - dom = conn.lookupByName(domain) - - conn.close() - state_names = { libvirt.VIR_DOMAIN_RUNNING : "running", - libvirt.VIR_DOMAIN_BLOCKED : "idle", - libvirt.VIR_DOMAIN_PAUSED : "paused", - libvirt.VIR_DOMAIN_SHUTDOWN : "in shutdown", - libvirt.VIR_DOMAIN_SHUTOFF : "shut off", - libvirt.VIR_DOMAIN_CRASHED : "crashed", - libvirt.VIR_DOMAIN_NOSTATE : "no state" } - return state_names[dom.info()[0]] -$$; - - -ALTER FUNCTION api.get_libvirt_domain_state(sysuri text, syspassword text, domain text) OWNER TO postgres; - --- --- Name: get_libvirt_domains(text, text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION get_libvirt_domains(sysuri text, syspassword text) RETURNS SETOF libvirt.domain_data - LANGUAGE plpython2u - AS $$ - #!/usr/bin/python - - import libvirt - import sys - - def request_credentials(credentials, data): - for credential in credentials: - if credential[0] == libvirt.VIR_CRED_AUTHNAME: - #credential[4] = sysuser - return 0 - elif credential[0] == libvirt.VIR_CRED_NOECHOPROMPT: - credential[4] = syspassword - else: - return -1 - - return 0 - - auth = [[libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_NOECHOPROMPT], request_credentials, None] - if syspassword == None: - conn = libvirt.open(sysuri) - else: - conn = libvirt.openAuth(sysuri, auth, 0) - - if conn == None: - sys.exit("Unable to connect") - - state_names = { libvirt.VIR_DOMAIN_RUNNING : "running", - libvirt.VIR_DOMAIN_BLOCKED : "idle", - libvirt.VIR_DOMAIN_PAUSED : "paused", - libvirt.VIR_DOMAIN_SHUTDOWN : "in shutdown", - libvirt.VIR_DOMAIN_SHUTOFF : "shut off", - libvirt.VIR_DOMAIN_CRASHED : "crashed", - libvirt.VIR_DOMAIN_NOSTATE : "no state" } - - domNames = () - for domID in conn.listDomainsID(): - domain = conn.lookupByID(domID) - domNames += ([domain.name(), state_names[domain.info()[0]], domain.XMLDesc(0)],) - - for dom in conn.listDefinedDomains(): - domain = conn.lookupByName(dom) - domNames += ([domain.name(), state_names[domain.info()[0]], domain.XMLDesc(0)],) - - conn.close() - return domNames -$$; - - -ALTER FUNCTION api.get_libvirt_domains(sysuri text, syspassword text) OWNER TO postgres; - --- --- Name: get_libvirt_platform(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_libvirt_platform(input_name text) RETURNS SETOF libvirt.platforms - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "libvirt"."platforms" WHERE "platform_name" = input_name); - END; -$$; - - -ALTER FUNCTION api.get_libvirt_platform(input_name text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_libvirt_platform(input_name text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_libvirt_platform(input_name text) IS 'Get a libvirt platform'; - - --- --- Name: get_local_user_level(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_local_user_level(input_user text) RETURNS text - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_user = 'root' THEN - RETURN 'admin'; - END IF; - - IF input_user IN (SELECT "user" FROM api.get_group_members(api.get_site_configuration('DEFAULT_LOCAL_ADMIN_GROUP'))) THEN - RETURN 'ADMIN'; - END IF; - - IF input_user IN (SELECT "user" FROM "management"."group_members" JOIN "management"."groups" ON "management"."groups"."group" = "management"."group_members"."group" WHERE "management"."groups"."privilege" = 'USER') THEN - RETURN 'USER'; - END IF; - - IF input_user IN (SELECT "user" FROM "management"."group_members" JOIN "management"."groups" ON "management"."groups"."group" = "management"."group_members"."group" WHERE "management"."groups"."privilege" = 'PROGRAM') THEN - RETURN 'PROGRAM'; - END IF; - - IF input_user IN (SELECT "user" FROM api.get_group_members(api.get_site_configuration('DEFAULT_LOCAL_USER_GROUP'))) THEN - RETURN 'USER'; - END IF; - - RETURN 'NONE'; - END; -$$; - - -ALTER FUNCTION api.get_local_user_level(input_user text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_local_user_level(input_user text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_local_user_level(input_user text) IS 'Get the users privilege level based on local tables'; - - --- --- Name: get_network_snmp(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_network_snmp(input_system_name text) RETURNS SETOF network.snmp - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF (SELECT "owner" FROM "systems"."systems" WHERE "system_name" = input_system_name) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission to get SNMP credentials denied: You are not owner or admin'; - END IF; - END IF; - - -- Return - RETURN QUERY (SELECT * FROM "network"."snmp" WHERE "system_name" = input_system_name); - END; -$$; - - -ALTER FUNCTION api.get_network_snmp(input_system_name text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_network_snmp(input_system_name text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_network_snmp(input_system_name text) IS 'Get SNMP connection information for a system'; - - --- --- Name: get_network_switchport(text, integer); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION get_network_switchport(text, integer) RETURNS SETOF network.switchports - LANGUAGE plperlu - AS $_$ - use strict; - use warnings; - use Net::SNMP; - - # Input parameters - my $systemName = shift(@_); - my $ifIndex = shift(@_); - - # Connection Details - my $snmpInfo = spi_exec_query("SELECT ro_community,address FROM network.snmp WHERE system_name = '$systemName'"); - my $host = $snmpInfo->{rows}[0]->{address}; - my $community = $snmpInfo->{rows}[0]->{ro_community}; - - # Date - my $date = spi_exec_query("SELECT localtimestamp(0)"); - $date = $date->{rows}[0]->{timestamp}; - my $user = spi_exec_query("SELECT api.get_current_user()"); - $user = $user->{rows}[0]->{get_current_user}; - - # OIDs - my $OID_ifName = ".1.3.6.1.2.1.31.1.1.1.1.$ifIndex"; - my $OID_ifDesc = ".1.3.6.1.2.1.2.2.1.2.$ifIndex"; - my $OID_ifAlias = ".1.3.6.1.2.1.31.1.1.1.18.$ifIndex"; - my $OID_ifOperStatus = ".1.3.6.1.2.1.2.2.1.8.$ifIndex"; - my $OID_ifAdminStatus = ".1.3.6.1.2.1.2.2.1.7.$ifIndex"; - my $OID_vmVlan = ".1.3.6.1.4.1.9.9.68.1.2.2.1.2.$ifIndex"; - - # Establish session - my ($session,$error) = Net::SNMP->session ( - -hostname => "$host", - -community => "$community", - ); - - # Check that it did not error - if (!defined($session)) { - die $error; - } - - # Data - my $result = $session->get_request( - -varbindlist => [ $OID_ifName, $OID_ifDesc, $OID_ifAlias, $OID_ifOperStatus, $OID_ifAdminStatus ] - ); - - # Check for errors - if(!defined($result)) { - die $session->error(); - } - - my $vlanResult = $session->get_request( - -varbindlist => [ $OID_vmVlan ] - ); - - # Gracefully disconnect - $session->close(); - - # Deal with results - if(!$vlanResult->{$OID_vmVlan}) { $result->{$OID_vmVlan} = undef; } else { $result->{$OID_vmVlan} = $vlanResult->{$OID_vmVlan}; } - if($result->{$OID_ifAlias} eq 'noSuchInstance') { $result->{$OID_ifAlias} = undef; } - if($result->{$OID_ifOperStatus}-1 == 0) { $result->{$OID_ifOperStatus} = 1; } else { $result->{$OID_ifOperStatus} = 0; } - if($result->{$OID_ifAdminStatus}-1 == 0) { $result->{$OID_ifAdminStatus} = 1; } else { $result->{$OID_ifAdminStatus} = 0; } - - # Return - return_next({system_name=>$systemName, name=>$result->{$OID_ifName}, desc=>$result->{$OID_ifDesc}, ifindex=>$ifIndex, alias=>$result->{$OID_ifAlias}, admin_state=>$result->{$OID_ifAdminStatus}, oper_state=>$result->{$OID_ifOperStatus}, vlan=>$result->{$OID_vmVlan},date_created=>$date, date_modified=>$date, last_modifier=>$user}); - return undef; -$_$; - - -ALTER FUNCTION api.get_network_switchport(text, integer) OWNER TO postgres; - --- --- Name: FUNCTION get_network_switchport(text, integer); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION get_network_switchport(text, integer) IS 'Get information on a specific switchport'; - - --- --- Name: get_network_switchports(text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION get_network_switchports(text) RETURNS SETOF integer - LANGUAGE plperlu - AS $_$ - use strict; - use warnings; - use Net::SNMP; - - # Input parameters - my $systemName = shift(@_); - - # Connection Details - my $snmpInfo = spi_exec_query("SELECT ro_community,address FROM network.snmp WHERE system_name = '$systemName'"); - my $host = $snmpInfo->{rows}[0]->{address}; - my $community = $snmpInfo->{rows}[0]->{ro_community}; - - # OIDs - my $OID_ifName = ".1.3.6.1.2.1.31.1.1.1.1"; - - # Establish session - my ($session,$error) = Net::SNMP->session ( - -hostname => "$host", - -community => "$community", - ); - - # Check that it did not error - if (!defined($session)) { - die $error; - } - - # Data - my $ifList = $session->get_table(-baseoid => $OID_ifName); - - # Check for errors - if(!defined($ifList)) { - die $session->error(); - } - - # Deal with results - while ( my ($ifIndex, $ifName) = each(%$ifList)) { - $ifIndex =~ s/$OID_ifName\.//; - return_next($ifIndex); - } - - # Gracefully disconnect - $session->close(); - - # Return - return undef; -$_$; - - -ALTER FUNCTION api.get_network_switchports(text) OWNER TO postgres; - --- --- Name: FUNCTION get_network_switchports(text); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION get_network_switchports(text) IS 'Get a list of all switchport indexes on a system'; - - --- --- Name: get_operating_systems(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_operating_systems() RETURNS SETOF text - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT "name" FROM "systems"."os" ORDER BY "name" ASC); - END; -$$; - - -ALTER FUNCTION api.get_operating_systems() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_operating_systems(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_operating_systems() IS 'Get a list of all available system types'; - - --- --- Name: get_os_distribution(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_os_distribution() RETURNS SETOF systems.os_distribution - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY(SELECT "os_name",count("os_name")::integer,round(count("os_name")::numeric/(SELECT count(*)::numeric FROM "systems"."systems")*100,0)::integer AS "percentage" - FROM "systems"."systems" - JOIN "systems"."os" ON "systems"."systems"."os_name" = "systems"."os"."name" - GROUP BY "os_name" - ORDER BY count("os_name") DESC); - END; -$$; - - -ALTER FUNCTION api.get_os_distribution() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_os_distribution(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_os_distribution() IS 'Get fun statistics on registered operating systems'; - - --- --- Name: get_os_family_distribution(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_os_family_distribution() RETURNS SETOF systems.os_family_distribution - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY(SELECT "family",count("family")::integer,round(count("family")::numeric/(SELECT count(*)::numeric FROM "systems"."systems")*100,0)::integer AS "percentage" - FROM "systems"."systems" - JOIN "systems"."os" ON "systems"."systems"."os_name" = "systems"."os"."name" - GROUP BY "family" - ORDER BY count("family") DESC); - END; -$$; - - -ALTER FUNCTION api.get_os_family_distribution() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_os_family_distribution(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_os_family_distribution() IS 'Get fun statistics on registered operating system families'; - - --- --- Name: get_owned_interface_addresses(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_owned_interface_addresses(input_owner text) RETURNS SETOF systems.interface_addresses - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_owner IS NULL THEN - RETURN QUERY (SELECT * FROM "systems"."interface_addresses"); - ELSE - RETURN QUERY (SELECT * FROM "systems"."interface_addresses" WHERE api.get_interface_address_owner("address") = input_owner); - END IF; - END; -$$; - - -ALTER FUNCTION api.get_owned_interface_addresses(input_owner text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_owned_interface_addresses(input_owner text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_owned_interface_addresses(input_owner text) IS 'Get all interface address data for all addresses owned by a given user'; - - --- --- Name: get_platforms(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_platforms() RETURNS SETOF systems.platforms - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "systems"."platforms" ORDER BY CASE WHEN "platform_name" = 'Custom' THEN 1 ELSE 2 END); - END; -$$; - - -ALTER FUNCTION api.get_platforms() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_platforms(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_platforms() IS 'Get information on all system platforms'; - - --- --- Name: get_range_addresses(inet, inet); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION get_range_addresses(inet, inet) RETURNS SETOF inet - LANGUAGE plperlu - AS $_X$ - use strict; - use warnings; - use Net::IP; - use Net::IP qw(:PROC); - use feature 'switch'; - - # Define range - my $range = new Net::IP ("$_[0] - $_[1]"); - my @addresses; - - # Loop through range - while ($range) - { - push(@addresses, ip_compress_address($range->ip(), 6)); - $range++; - } - - # Done - return \@addresses; -$_X$; - - -ALTER FUNCTION api.get_range_addresses(inet, inet) OWNER TO postgres; - --- --- Name: FUNCTION get_range_addresses(inet, inet); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION get_range_addresses(inet, inet) IS 'return a list of all addresses within a given range'; - - --- --- Name: get_range_groups(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_range_groups(input_name text) RETURNS SETOF management.groups - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "management"."groups" WHERE "group" IN (SELECT "group_name" FROM "ip"."range_groups" WHERE "range_name" = input_name) ORDER BY "group"); - END; -$$; - - -ALTER FUNCTION api.get_range_groups(input_name text) OWNER TO starrs_admin; - --- --- Name: get_range_top_users(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_range_top_users(input_name text) RETURNS TABLE("user" text, count integer) - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY( - SELECT - api.get_interface_address_owner(address), - count(api.get_interface_address_owner(address))::integer - FROM - systems.interface_addresses - WHERE api.get_address_range(address) = input_name - GROUP BY api.get_interface_address_owner(address) - ORDER BY count(api.get_interface_address_owner(address)) - DESC limit 10 - ); - END; -$$; - - -ALTER FUNCTION api.get_range_top_users(input_name text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_range_top_users(input_name text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_range_top_users(input_name text) IS 'Get the top 10 users of range addresses'; - - --- --- Name: get_range_utilization(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_range_utilization(input_range text) RETURNS TABLE(inuse integer, free integer, total integer) - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY ( - SELECT COUNT("systems"."interface_addresses"."address")::integer AS "inuse", - (api.get_ip_range_total(input_range) - COUNT("systems"."interface_addresses"."address"))::integer AS "free", - api.get_ip_range_total(input_range)::integer AS "total" - FROM "systems"."interface_addresses" - WHERE api.get_address_range("address") = input_range); - END; -$$; - - -ALTER FUNCTION api.get_range_utilization(input_range text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_range_utilization(input_range text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_range_utilization(input_range text) IS 'Get statistics on range utilization'; - - --- --- Name: get_record_types(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_record_types() RETURNS SETOF text - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT "type" FROM "dns"."types" ORDER BY "type" ASC); - END; -$$; - - -ALTER FUNCTION api.get_record_types() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_record_types(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_record_types() IS 'Get all of the valid DNS types for this application'; - - --- --- Name: get_reverse_domain(inet); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION get_reverse_domain(inet) RETURNS text - LANGUAGE plperlu - AS $_X$ - use strict; - use warnings; - use Net::IP; - use Net::IP qw(:PROC); - - # Return the rdns string for nsupdate from the given address. Automagically figures out IPv4 and IPv6. - my $reverse_domain = new Net::IP ($_[0])->reverse_ip() or die (Net::IP::Error()); - $reverse_domain =~ s/\.$//; - return $reverse_domain; - -$_X$; - - -ALTER FUNCTION api.get_reverse_domain(inet) OWNER TO postgres; - --- --- Name: FUNCTION get_reverse_domain(inet); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION get_reverse_domain(inet) IS 'Use a convenient Perl module to generate and return the RDNS record for a given address'; - - --- --- Name: get_search_data(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_search_data() RETURNS SETOF management.search_data - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT - "systems"."systems"."datacenter", - (SELECT "zone" FROM "ip"."ranges" WHERE "name" = "api"."get_address_range"("systems"."interface_addresses"."address")) AS "availability_zone", - "systems"."systems"."system_name", - "systems"."systems"."location", - "systems"."systems"."asset", - "systems"."systems"."group", - "systems"."systems"."platform_name", - "systems"."interfaces"."mac", - "systems"."interface_addresses"."address", - "systems"."interface_addresses"."config", - "systems"."systems"."owner" AS "system_owner", - "systems"."systems"."last_modifier" AS "system_last_modifier", - "api"."get_address_range"("systems"."interface_addresses"."address") AS "range", - "dns"."a"."hostname", - "dns"."cname"."alias", - "dns"."srv"."alias", - "dns"."a"."zone", - "dns"."a"."owner" AS "dns_owner", - "dns"."a"."last_modifier" AS "dns_last_modifier" -FROM "systems"."systems" -LEFT JOIN "systems"."interfaces" ON "systems"."interfaces"."system_name" = "systems"."systems"."system_name" -LEFT JOIN "systems"."interface_addresses" ON "systems"."interface_addresses"."mac" = "systems"."interfaces"."mac" -LEFT JOIN "dns"."a" ON "dns"."a"."address" = "systems"."interface_addresses"."address" -LEFT JOIN "dns"."cname" ON "dns"."cname"."address" = "systems"."interface_addresses"."address" -LEFT JOIN "dns"."srv" ON "dns"."srv"."address" = "systems"."interface_addresses"."address" -ORDER BY "systems"."interface_addresses"."address","systems"."interfaces"."mac"); - END; -$$; - - -ALTER FUNCTION api.get_search_data() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_search_data(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_search_data() IS 'Get search data to parse'; - - --- --- Name: get_site_configuration_all(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_site_configuration_all() RETURNS SETOF management.configuration - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "management"."configuration" ORDER BY "option" ASC); - END; -$$; - - -ALTER FUNCTION api.get_site_configuration_all() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_site_configuration_all(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_site_configuration_all() IS 'Get all site configuration directives'; - - --- --- Name: get_subnet_addresses(cidr); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION get_subnet_addresses(cidr) RETURNS SETOF inet - LANGUAGE plperlu - AS $_X$ - use strict; - use warnings; - use Net::IP; - use Net::IP qw(:PROC); - use feature 'switch'; - - # Define some basic information about the network. - my $subnet = new Net::IP ($_[0]) or die (Net::IP::Error()); - my $broadcast_address = $subnet->last_ip(); - my $network_address = $subnet->ip(); - my $version = ip_get_version($network_address); - - # Create an object of the range between the network address and the broadcast address. - my $range = new Net::IP ("$network_address - $broadcast_address"); - my @addresses; - - # Given/When is the new Switch. Perform different operations for IPv4 and IPv6. - given ($version) { - when (/4/) { - while (++$range) { - # While they technically work, .255 and .0 addresses in multi-range wide networks - # can cause confusion and possibly device problems. Well just avoid them alltogether. - if($range->ip() !~ m/\.0$|\.255$/) { - push(@addresses, $range->ip()); - } - } - } - when (/6/) { - while (++$range) { - push(@addresses, ip_compress_address($range->ip(), 6)); - } - } - default { die "Unable to generate\n"; } - } - - # Done - return \@addresses; -$_X$; - - -ALTER FUNCTION api.get_subnet_addresses(cidr) OWNER TO postgres; - --- --- Name: FUNCTION get_subnet_addresses(cidr); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION get_subnet_addresses(cidr) IS 'Given a subnet, return an array of all acceptable addresses within that subnet.'; - - --- --- Name: get_subnet_utilization(cidr); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_subnet_utilization(input_subnet cidr) RETURNS TABLE(inuse integer, free integer, total integer) - LANGUAGE plpgsql - AS $$ - DECLARE - addrcount INTEGER; - BEGIN - -- Total - SELECT COUNT("address")::integer INTO addrcount - FROM "ip"."addresses" WHERE "address" << input_subnet; - - RETURN QUERY ( - SELECT COUNT("systems"."interface_addresses"."address"):: integer AS "inuse", - addrcount - COUNT("systems"."interface_addresses"."address"):: integer as "free", - addrcount AS "total" - FROM "systems"."interface_addresses" - WHERE "address" << input_subnet - ); - END; -$$; - - -ALTER FUNCTION api.get_subnet_utilization(input_subnet cidr) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_subnet_utilization(input_subnet cidr); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_subnet_utilization(input_subnet cidr) IS 'Get statistics on subnet utilization'; - - --- --- Name: get_switchview_bridgeportid(inet, text, integer); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION get_switchview_bridgeportid(inet, text, integer) RETURNS TABLE(camportinstanceid text, bridgeportid integer) - LANGUAGE plperlu - AS $_$ - use strict; - use warnings; - use Net::SNMP; - use Socket; - - # Define OIDs - my $dot1dTpFdbPort = ".1.3.6.1.2.1.17.4.3.1.2"; - - # Needed Variables - my $hostname = shift(@_) or die "Unable to get host"; - my $community = shift(@_) or die "Unable to get READ community"; - my $vlan = shift(@_) or die "Unable to get VLANID"; - - # Establish session - my ($session,$error) = Net::SNMP->session ( - -hostname => "$hostname", - -community => "$community\@$vlan", - ); - - # Check that it did not error - if (!defined($session)) { - die $error; - } - - # Get a list of all data - my $bridgePortList = $session->get_table(-baseoid => $dot1dTpFdbPort); - - # Do something for each item of the list - while ( my ($camPortInstanceID, $bridgePortID) = each(%$bridgePortList)) { - $camPortInstanceID =~ s/$dot1dTpFdbPort//; - return_next({camportinstanceid=>$camPortInstanceID, bridgeportid=>$bridgePortID}); - } - - # Gracefully disconnect - $session->close(); - - # Return - return undef; -$_$; - - -ALTER FUNCTION api.get_switchview_bridgeportid(inet, text, integer) OWNER TO postgres; - --- --- Name: FUNCTION get_switchview_bridgeportid(inet, text, integer); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION get_switchview_bridgeportid(inet, text, integer) IS 'Get a mapping of CAM instanceIDs and bridgeIDs'; - - --- --- Name: get_switchview_cam(inet, text, integer); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION get_switchview_cam(inet, text, integer) RETURNS TABLE(camportinstanceid text, mac macaddr) - LANGUAGE plperlu - AS $_X$ - #!/usr/bin/perl -w - - use strict; - use warnings; - use Net::SNMP; - use Socket; - - # Define OIDs - my $dot1dTpFdbAddress = ".1.3.6.1.2.1.17.4.3.1.1"; - - # Needed Variables - my $hostname = shift(@_) or die "Unable to get host"; - my $community = shift(@_) or die "Unable to get READ community"; - my $vlan = shift(@_) or die "Unable to get VLANID"; - - # Subroutine to format a MAC address to something nice - sub format_raw_mac { - my $mac = $_[0]; - # Get rid of the hex identifier - $mac =~ s/^0x//; - - # Make groups of two characters - $mac =~ s/(.{2})/$1:/gg; - - # Remove the trailing : left by the previous function - $mac =~ s/\:$//; - - # Spit it back out - return $mac; - } - - # Establish session - my ($session,$error) = Net::SNMP->session ( - -hostname => "$hostname", - -community => "$community\@$vlan", - ); - - # Check that it did not error - if (!defined($session)) { - die $error; - } - - # Get a list of all data - my $camList = $session->get_table(-baseoid => $dot1dTpFdbAddress); - - # Do something for each item of the list - while ( my ($camPortInstanceID, $macaddr) = each(%$camList)) { - $camPortInstanceID =~ s/$dot1dTpFdbAddress//; - - # Sometimes there are non-valid MAC addresses in the CAM. - if($macaddr =~ m/[0-9a-fA-F]{12}/) { - $macaddr = format_raw_mac($macaddr); - #print "InstanceID: $camPortInstanceID - MAC: $macaddr\n"; - return_next({camportinstanceid=>$camPortInstanceID,mac=>$macaddr}); - } - } - - # Gracefully disconnect - $session->close(); - - # Return - return undef; - -$_X$; - - -ALTER FUNCTION api.get_switchview_cam(inet, text, integer) OWNER TO postgres; - --- --- Name: FUNCTION get_switchview_cam(inet, text, integer); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION get_switchview_cam(inet, text, integer) IS 'Get the CAM/MAC table from a device on a certain VLAN'; - - --- --- Name: get_switchview_device_cam(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_switchview_device_cam(input_system text) RETURNS SETOF network.cam - LANGUAGE plpgsql - AS $$ - DECLARE - Vlans RECORD; - CamData RECORD; - input_host INET; - input_community TEXT; - BEGIN - SELECT get_system_primary_address::inet INTO input_host FROM api.get_system_primary_address(input_system); - IF input_host IS NULL THEN - RAISE EXCEPTION 'Unable to find address for system %',input_system; - END IF; - SELECT ro_community INTO input_community FROM api.get_network_snmp(input_system); - IF input_community IS NULL THEN - RAISE EXCEPTION 'Unable to find SNMP settings for system %',input_system; - END IF; - - FOR Vlans IN (SELECT "vlan" FROM "network"."vlans" WHERE "datacenter" = (SELECT "datacenter" FROM "systems"."systems" WHERE "system_name" = input_system) AND "vlan" IS NOT NULL GROUP BY "vlan" ORDER BY "vlan") LOOP - FOR CamData IN ( - SELECT mac,portindex.ifindex,Vlans.vlan FROM api.get_switchview_cam(input_host,input_community,vlans.vlan) AS "cam" - JOIN api.get_switchview_bridgeportid(input_host,input_community,vlans.vlan) AS "bridgeportid" - ON bridgeportid.camportinstanceid = cam.camportinstanceid - JOIN api.get_switchview_portindex(input_host,input_community,vlans.vlan) AS "portindex" - ON bridgeportid.bridgeportid = portindex.bridgeportid - ) LOOP - RETURN NEXT CamData; - END LOOP; - END LOOP; - RETURN; - END; -$$; - - -ALTER FUNCTION api.get_switchview_device_cam(input_system text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_switchview_device_cam(input_system text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_switchview_device_cam(input_system text) IS 'Get all CAM data from a particular device'; - - --- --- Name: get_switchview_device_switchports(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_switchview_device_switchports(input_system text) RETURNS SETOF network.switchports - LANGUAGE plpgsql - AS $$ - DECLARE - system_address INET; - system_community TEXT; - BEGIN - SELECT get_system_primary_address::inet INTO system_address FROM api.get_system_primary_address(input_system); - IF system_address IS NULL THEN - RAISE EXCEPTION 'Unable to find address for system %',input_system; - END IF; - SELECT ro_community INTO system_community FROM api.get_network_snmp(input_system); - IF system_community IS NULL THEN - RAISE EXCEPTION 'Unable to find SNMP settings for system %',input_system; - END IF; - - RETURN QUERY ( - SELECT "ifadminstatus","ifoperstatus","ifname","ifdesc","ifalias" - FROM api.get_switchview_port_names(system_address, system_community) AS "namedata" - JOIN api.get_switchview_port_adminstatus(system_address, system_community) AS "admindata" - ON "admindata"."ifindex" = "namedata"."ifindex" - JOIN api.get_switchview_port_operstatus(system_address, system_community) AS "operdata" - ON "operdata"."ifindex" = "namedata"."ifindex" - JOIN api.get_switchview_port_descriptions(system_address, system_community) AS "descdata" - ON "descdata"."ifindex" = "namedata"."ifindex" - ); - END; -$$; - - -ALTER FUNCTION api.get_switchview_device_switchports(input_system text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_switchview_device_switchports(input_system text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_switchview_device_switchports(input_system text) IS 'Get data on all switchports on a system'; - - --- --- Name: get_switchview_neighbors(inet, text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION get_switchview_neighbors(inet, text) RETURNS TABLE("localifIndex" integer, remoteifdesc text, remotehostname text) - LANGUAGE plperlu - AS $_$ - use strict; - use warnings; - use Net::SNMP; - use Socket; - use 5.10.0; - - # Define OIDs - my $cdpCacheEntry = "1.3.6.1.4.1.9.9.23.1.2.1.1"; - my $cdpCacheIfIndex = "1"; - my $cdpCacheDeviceId = "6"; - my $cdpCacheDevicePort = "7"; - my $cdpCachePlatform = "8"; - - # Needed Variables - my $hostname = shift(@_) or die "Unable to get host"; - my $community = shift(@_) or die "Unable to get READ community"; - - # Data containers - my %remoteHosts; - my %remotePorts; - my %remotePlatforms; - my %localPorts; - - # Establish session - my ($session,$error) = Net::SNMP->session ( - -hostname => "$hostname", - -community => "$community", - ); - - # Check that it did not error - if (!defined($session)) { - print $error; - exit 1; - } - - # Get a list of all data - my $neighborList = $session->get_table(-baseoid => $cdpCacheEntry); - - # Do something for each item of the list - while ( my ($id, $value) = each(%$neighborList)) { - $id=~ s/$cdpCacheEntry\.//; - - if($id =~ m/^($cdpCacheDeviceId|$cdpCacheDevicePort|$cdpCachePlatform|$cdpCacheIfIndex)\./) { - my @cdpEntry = split(/\./,$id); - - given ($cdpEntry[0]) { - when(/$cdpCacheDeviceId/) { - $remoteHosts{$cdpEntry[1]} = $value; - } - when(/$cdpCacheDevicePort/) { - $remotePorts{$cdpEntry[1]} = $value; - } - when(/$cdpCachePlatform/) { - $remotePlatforms{$cdpEntry[1]} = $value; - } - } - } - } - - foreach my $ifIndex (keys(%remoteHosts)) { - return_next({localifIndex=>$ifIndex,remoteifdesc=>$remotePorts{$ifIndex}, remotehostname=>$remoteHosts{$ifIndex}}); - } - - # Gracefully disconnect - $session->close(); - - # Return - return undef; - -$_$; - - -ALTER FUNCTION api.get_switchview_neighbors(inet, text) OWNER TO postgres; - --- --- Name: FUNCTION get_switchview_neighbors(inet, text); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION get_switchview_neighbors(inet, text) IS 'Get the CDP table from a device to see who it is attached to'; - - --- --- Name: get_switchview_port_adminstatus(inet, text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION get_switchview_port_adminstatus(inet, text) RETURNS TABLE(ifindex integer, ifadminstatus boolean) - LANGUAGE plperlu - AS $_$ - use strict; - use warnings; - use Net::SNMP; - use Socket; - - # Define OIDs - my $ifAdminStatus = ".1.3.6.1.2.1.2.2.1.7"; - - # Needed Variables - my $hostname = shift(@_) or die "Unable to get host"; - my $community = shift(@_) or die "Unable to get READ community"; - - # Establish session - my ($session,$error) = Net::SNMP->session ( - -hostname => "$hostname", - -community => "$community", - ); - - # Check that it did not error - if (!defined($session)) { - die $error; - } - - # Get a list of all data - my $portStates = $session->get_table(-baseoid => $ifAdminStatus); - - # Do something for each item of the list - while ( my ($portIndex, $portState) = each(%$portStates)) { - $portIndex =~ s/$ifAdminStatus\.//; - if($portState-1 == 0) { - # Then its up - $portState = 1; - } - else { - # Then its down - $portState = 0; - } - return_next({ifindex=>$portIndex, ifadminstatus=>$portState}); - } - - # Gracefully disconnect - $session->close(); - - # Return - return undef; - -$_$; - - -ALTER FUNCTION api.get_switchview_port_adminstatus(inet, text) OWNER TO postgres; - --- --- Name: FUNCTION get_switchview_port_adminstatus(inet, text); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION get_switchview_port_adminstatus(inet, text) IS 'Map ifindexes to port administrative status'; - - --- --- Name: get_switchview_port_descriptions(inet, text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION get_switchview_port_descriptions(inet, text) RETURNS TABLE(ifindex integer, ifalias text) - LANGUAGE plperlu - AS $_$ - use strict; - use warnings; - use Net::SNMP; - use Socket; - - # Define OIDs - my $ifAlias = "1.3.6.1.2.1.31.1.1.1.18"; - - # Needed Variables - my $hostname = shift(@_) or die "Unable to get host"; - my $community = shift(@_) or die "Unable to get READ community"; - - # Establish session - my ($session,$error) = Net::SNMP->session ( - -hostname => "$hostname", - -community => "$community", - ); - - # Check that it did not error - if (!defined($session)) { - die $error; - } - - # Get a list of all data - my $portAliases = $session->get_table(-baseoid => $ifAlias); - - # Do something for each item of the list - while ( my ($portIndex, $portAlias) = each(%$portAliases)) { - $portIndex =~ s/$ifAlias\.//; - return_next({ifindex=>$portIndex, ifalias=>$portAlias}); - } - - # Gracefully disconnect - $session->close(); - - # Return - return undef; - -$_$; - - -ALTER FUNCTION api.get_switchview_port_descriptions(inet, text) OWNER TO postgres; - --- --- Name: FUNCTION get_switchview_port_descriptions(inet, text); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION get_switchview_port_descriptions(inet, text) IS 'Map ifindexes to port descriptions (or aliases in Cisco-land)'; - - --- --- Name: get_switchview_port_names(inet, text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION get_switchview_port_names(inet, text) RETURNS TABLE(ifindex integer, ifname text, ifdesc text) - LANGUAGE plperlu - AS $_$ - use strict; - use warnings; - use Net::SNMP; - use Socket; - - # Define OIDs - my $ifName = ".1.3.6.1.2.1.31.1.1.1.1"; - my $ifDesc = ".1.3.6.1.2.1.2.2.1.2"; - - # Needed Variables - my $hostname = shift(@_) or die "Unable to get host"; - my $community = shift(@_) or die "Unable to get READ community"; - my %ports; - - # Establish session - my ($session,$error) = Net::SNMP->session ( - -hostname => "$hostname", - -community => "$community", - ); - - # Check that it did not error - if (!defined($session)) { - die $error; - } - - # Get a list of all data - my $portNameList = $session->get_table(-baseoid => $ifName); - my $portDescList = $session->get_table(-baseoid => $ifDesc); - - # Do something for each item of the list - while ( my ($portIndex, $portName) = each(%$portNameList)) { - $portIndex =~ s/$ifName\.//; - $ports{$portIndex}{'ifName'} = $portName; - } - while ( my ($portIndex, $portDesc) = each(%$portDescList)) { - $portIndex =~ s/$ifDesc\.//; - $ports{$portIndex}{'ifDesc'} = $portDesc; - } - foreach my $key (keys(%ports)) { - return_next({ifindex=>$key, ifname=>$ports{$key}{'ifName'}, ifdesc=>$ports{$key}{'ifDesc'}}); - } - - # Gracefully disconnect - $session->close(); - - # Return - return undef; - -$_$; - - -ALTER FUNCTION api.get_switchview_port_names(inet, text) OWNER TO postgres; - --- --- Name: FUNCTION get_switchview_port_names(inet, text); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION get_switchview_port_names(inet, text) IS 'Map ifindexes to port names'; - - --- --- Name: get_switchview_port_operstatus(inet, text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION get_switchview_port_operstatus(inet, text) RETURNS TABLE(ifindex integer, ifoperstatus boolean) - LANGUAGE plperlu - AS $_$ - use strict; - use warnings; - use Net::SNMP; - use Socket; - - # Define OIDs - my $ifOperStatus = ".1.3.6.1.2.1.2.2.1.8"; - - # Needed Variables - my $hostname = shift(@_) or die "Unable to get host"; - my $community = shift(@_) or die "Unable to get READ community"; - - # Establish session - my ($session,$error) = Net::SNMP->session ( - -hostname => "$hostname", - -community => "$community", - ); - - # Check that it did not error - if (!defined($session)) { - die $error; - } - - # Get a list of all data - my $portStates = $session->get_table(-baseoid => $ifOperStatus); - - # Do something for each item of the list - while ( my ($portIndex, $portState) = each(%$portStates)) { - $portIndex =~ s/$ifOperStatus\.//; - if($portState-1 == 0) { - # Then its up - $portState = 1; - } - else { - # Then its down - $portState = 0; - } - return_next({ifindex=>$portIndex, ifoperstatus=>$portState}); - } - - # Gracefully disconnect - $session->close(); - - # Return - return undef; - -$_$; - - -ALTER FUNCTION api.get_switchview_port_operstatus(inet, text) OWNER TO postgres; - --- --- Name: FUNCTION get_switchview_port_operstatus(inet, text); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION get_switchview_port_operstatus(inet, text) IS 'Map ifindexes to port operational status'; - - --- --- Name: get_switchview_portindex(inet, text, integer); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION get_switchview_portindex(inet, text, integer) RETURNS TABLE(bridgeportid integer, ifindex integer) - LANGUAGE plperlu - AS $_$ - use strict; - use warnings; - use Net::SNMP; - use Socket; - - # Define OIDs - my $dot1dBasePortIfIndex = ".1.3.6.1.2.1.17.1.4.1.2"; - - # Needed Variables - my $hostname = shift(@_) or die "Unable to get host"; - my $community = shift(@_) or die "Unable to get READ community"; - my $vlan = shift(@_) or die "Unable to get VLAN"; - - # Establish session - my ($session,$error) = Net::SNMP->session ( - -hostname => "$hostname", - -community => "$community\@$vlan" - ); - - # Check that it did not error - if (!defined($session)) { - die $error; - } - - # Get a list of all data - my $portIndexList = $session->get_table(-baseoid => $dot1dBasePortIfIndex); - - # Do something for each item of the list - while ( my ($bridgePortID, $portIndex) = each(%$portIndexList)) { - $bridgePortID =~ s/$dot1dBasePortIfIndex\.//; - return_next({bridgeportid=>$bridgePortID, ifindex=>$portIndex}); - } - - # Gracefully disconnect - $session->close(); - - # Return - return undef; - -$_$; - - -ALTER FUNCTION api.get_switchview_portindex(inet, text, integer) OWNER TO postgres; - --- --- Name: FUNCTION get_switchview_portindex(inet, text, integer); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION get_switchview_portindex(inet, text, integer) IS 'Get a mapping of port indexes to bridge indexes'; - - --- --- Name: get_system(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_system(input_system_name text) RETURNS SETOF systems.systems - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "systems"."systems" WHERE "system_name" = input_system_name); - END; -$$; - - -ALTER FUNCTION api.get_system(input_system_name text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_system(input_system_name text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_system(input_system_name text) IS 'Get a single system'; - - -SET search_path = systems, pg_catalog; - --- --- Name: architectures; Type: TABLE; Schema: systems; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE architectures ( - architecture text NOT NULL, - comment text, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE systems.architectures OWNER TO starrs_admin; - --- --- Name: TABLE architectures; Type: COMMENT; Schema: systems; Owner: starrs_admin --- - -COMMENT ON TABLE architectures IS 'The CPU architecture of a platform'; - - -SET search_path = api, pg_catalog; - --- --- Name: get_system_architectures(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_system_architectures() RETURNS SETOF systems.architectures - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "systems"."architectures" ORDER BY CASE WHEN "architecture" = 'i386' THEN 1 ELSE 2 END); - END; -$$; - - -ALTER FUNCTION api.get_system_architectures() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_system_architectures(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_system_architectures() IS 'Get all the available system architectures'; - - --- --- Name: get_system_cam(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_system_cam(input_system_name text) RETURNS SETOF network.cam_cache - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF (SELECT "owner" FROM "systems"."systems" WHERE "system_name" = input_system_name) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission to get CAM denied: You are not owner or admin'; - END IF; - END IF; - - RETURN QUERY (SELECT * FROM "network"."cam_cache" WHERE "system_name" = input_system_name ORDER BY "vlan","ifindex","mac"); - END; -$$; - - -ALTER FUNCTION api.get_system_cam(input_system_name text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_system_cam(input_system_name text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_system_cam(input_system_name text) IS 'Get the latest CAM data from the cache'; - - --- --- Name: get_system_interface_address(inet); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_system_interface_address(input_address inet) RETURNS SETOF systems.interface_addresses - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "systems"."interface_addresses" WHERE "address" = input_address); - END; -$$; - - -ALTER FUNCTION api.get_system_interface_address(input_address inet) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_system_interface_address(input_address inet); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_system_interface_address(input_address inet) IS 'Get all interface address data for an address'; - - --- --- Name: get_system_interface_addresses(macaddr); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_system_interface_addresses(input_mac macaddr) RETURNS SETOF systems.interface_addresses - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_mac IS NULL THEN - RETURN QUERY (SELECT * FROM "systems"."interface_addresses" ORDER BY family(address),address); - ELSE - RETURN QUERY (SELECT * FROM "systems"."interface_addresses" WHERE "mac" = input_mac ORDER BY family(address),address ASC); - END IF; - END; -$$; - - -ALTER FUNCTION api.get_system_interface_addresses(input_mac macaddr) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_system_interface_addresses(input_mac macaddr); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_system_interface_addresses(input_mac macaddr) IS 'Get all interface addresses on a specified MAC'; - - --- --- Name: get_system_interface_data(macaddr); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_system_interface_data(input_mac macaddr) RETURNS SETOF systems.interfaces - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "systems"."interfaces" WHERE "mac" = input_mac); - END; -$$; - - -ALTER FUNCTION api.get_system_interface_data(input_mac macaddr) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_system_interface_data(input_mac macaddr); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_system_interface_data(input_mac macaddr) IS 'Get all interface information on a system for a specific interface'; - - --- --- Name: get_system_interfaces(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_system_interfaces(input_system_name text) RETURNS SETOF systems.interfaces - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_system_name IS NULL THEN - RETURN QUERY (SELECT * FROM "systems"."interfaces" ORDER BY mac); - ELSE - RETURN QUERY (SELECT * FROM "systems"."interfaces" WHERE "system_name" = input_system_name ORDER BY mac); - END IF; - END; -$$; - - -ALTER FUNCTION api.get_system_interfaces(input_system_name text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_system_interfaces(input_system_name text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_system_interfaces(input_system_name text) IS 'Get all interface information on a system'; - - --- --- Name: get_system_owner(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_system_owner(input_system text) RETURNS text - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN (SELECT "owner" FROM "systems"."systems" WHERE "system_name" = input_system); - END; -$$; - - -ALTER FUNCTION api.get_system_owner(input_system text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_system_owner(input_system text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_system_owner(input_system text) IS 'Easily get the owner of a system'; - - --- --- Name: get_system_permissions(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_system_permissions(input_system_name text) RETURNS TABLE(read boolean, write boolean) - LANGUAGE plpgsql - AS $$ - DECLARE - read BOOLEAN; - write BOOLEAN; - sysowner TEXT; - sysgroup TEXT; - BEGIN - SELECT "owner","group" INTO sysowner, sysgroup - FROM "systems"."systems" - WHERE "system_name" = input_system_name; - - IF sysowner IS NULL THEN - RAISE EXCEPTION 'System % not found!',input_system_name; - END IF; - - IF sysgroup IN (SELECT * FROM api.get_current_user_groups()) THEN - IF api.get_current_user() IN (SELECT * FROM api.get_group_admins(sysgroup)) THEN - read := TRUE; - write := TRUE; - ELSE - read := TRUE; - write := FALSE; - END IF; - ELSE - read := TRUE; - write := FALSE; - END IF; - - IF sysowner = api.get_current_user() THEN - read := TRUE; - write := TRUE; - - END IF; - - IF api.get_current_user_level() ~* 'ADMIN' THEN - read := TRUE; - write := TRUE; - END IF; - RETURN QUERY (SELECT read, write); - END; -$$; - - -ALTER FUNCTION api.get_system_permissions(input_system_name text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_system_permissions(input_system_name text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_system_permissions(input_system_name text) IS 'Get the current user permissions on a system'; - - --- --- Name: get_system_primary_address(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_system_primary_address(input_system_name text) RETURNS inet - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN (SELECT "address" FROM "systems"."systems" - JOIN "systems"."interfaces" ON "systems"."interfaces"."system_name" = "systems"."systems"."system_name" - JOIN "systems"."interface_addresses" ON "systems"."interfaces"."mac" = "systems"."interface_addresses"."mac" - WHERE "isprimary" = TRUE AND "systems"."systems"."system_name" = input_system_name - ORDER BY "systems"."interfaces"."mac" DESC LIMIT 1); - END; -$$; - - -ALTER FUNCTION api.get_system_primary_address(input_system_name text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_system_primary_address(input_system_name text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_system_primary_address(input_system_name text) IS 'Get the primary address of a system'; - - --- --- Name: get_system_switchports(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_system_switchports(input_system text) RETURNS SETOF network.switchports - LANGUAGE plpgsql - AS $$ - DECLARE - IfIndexes RECORD; - Ints network.switchports%rowtype; - BEGIN - FOR IfIndexes IN (SELECT * FROM api.get_network_switchports(input_system) ORDER BY get_network_switchports) LOOP - --RETURN NEXT api.get_network_switchport(input_system, IfIndexes.get_network_switchports); - SELECT * FROM api.get_network_switchport(input_system, IfIndexes.get_network_switchports) INTO Ints; - RETURN NEXT Ints; - END LOOP; - RETURN; - END; -$$; - - -ALTER FUNCTION api.get_system_switchports(input_system text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_system_switchports(input_system text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_system_switchports(input_system text) IS 'Get the most recent cached switchport data'; - - -SET search_path = systems, pg_catalog; - --- --- Name: device_types; Type: TABLE; Schema: systems; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE device_types ( - type text NOT NULL, - family text NOT NULL, - CONSTRAINT device_types_family_check CHECK ((family ~ '^PC|Network$'::text)) -); - - -ALTER TABLE systems.device_types OWNER TO starrs_admin; - --- --- Name: TABLE device_types; Type: COMMENT; Schema: systems; Owner: starrs_admin --- - -COMMENT ON TABLE device_types IS 'Computers are different than switches and routers, as they appear in the network overview.'; - - -SET search_path = api, pg_catalog; - --- --- Name: get_system_types(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_system_types() RETURNS SETOF systems.device_types - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "systems"."device_types" ORDER BY "type"); - END; -$$; - - -ALTER FUNCTION api.get_system_types() OWNER TO starrs_admin; - --- --- Name: FUNCTION get_system_types(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_system_types() IS 'Get a list of all available system types'; - - --- --- Name: get_systems(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_systems(input_username text) RETURNS SETOF systems.systems - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_username IS NULL THEN - RETURN QUERY (SELECT * FROM "systems"."systems" ORDER BY lower("system_name") ASC); - ELSE - RETURN QUERY (SELECT * FROM "systems"."systems" WHERE "owner" = input_username ORDER BY lower("system_name") ASC); - END IF; - END; -$$; - - -ALTER FUNCTION api.get_systems(input_username text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_systems(input_username text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_systems(input_username text) IS 'Get all system names owned by a given user'; - - --- --- Name: get_user_email(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_user_email(input_user text) RETURNS text - LANGUAGE plpgsql - AS $_$ - BEGIN - IF api.get_site_configuration('USER_PRIVILEGE_SOURCE') ~* '^ad$' THEN - RETURN api.get_ad_user_email(input_user); - ELSE - RETURN input_user||'@'||api.get_site_configuration('EMAIL_DOMAIN'); - END IF; - END; -$_$; - - -ALTER FUNCTION api.get_user_email(input_user text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_user_email(input_user text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_user_email(input_user text) IS 'Get the email address of a user'; - - --- --- Name: get_user_groups(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_user_groups(input_user text) RETURNS SETOF management.groups - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT * FROM "management"."groups" WHERE "group" IN ( - SELECT "group" FROM "management"."group_members" WHERE "user" = input_user) - ORDER BY "group" - ); - END; -$$; - - -ALTER FUNCTION api.get_user_groups(input_user text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_user_groups(input_user text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_user_groups(input_user text) IS 'Get all of the groups that a user belongs to'; - - --- --- Name: get_user_ranges(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_user_ranges(input_user text) RETURNS SETOF ip.ranges - LANGUAGE plpgsql - AS $$ - DECLARE - UserGroups RECORD; - GroupRanges RECORD; - RangeData RECORD; - BEGIN - --IF api.get_current_user_level() ~* 'ADMIN' THEN - -- RETURN QUERY (SELECT * FROM "ip"."ranges" ORDER BY "name"); - --END IF; - - FOR UserGroups IN (SELECT "group" FROM "management"."group_members" WHERE "user" = input_user) LOOP - FOR RangeData IN (SELECT * FROM api.get_group_ranges(UserGroups."group")) LOOP - RETURN NEXT RangeData; - END LOOP; - END LOOP; - - RETURN; - END; -$$; - - -ALTER FUNCTION api.get_user_ranges(input_user text) OWNER TO starrs_admin; - --- --- Name: get_vcloud_group_members(text, text, text, text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION get_vcloud_group_members(text, text, text, text) RETURNS SETOF text - LANGUAGE plperlu - AS $_X$ - use strict; - use warnings; - use VMware::vCloud; - use Data::Dumper; - - # Connection Information - my $hostname = $_[0] or die "Unable to get hostname"; - my $org = $_[1] or die "Unable to get organization"; - my $username = $_[2] or die "Unable to get username"; - my $password = $_[3] or die "Unable to get password"; - - # Create Connection - my $vcd = new VMware::vCloud ( $hostname, $username, $password, $org ); - - # Make sure we got an organization - if(!$vcd->{raw_login_data}->{Org}->{$org}->{href}) { die "Unable to find organization: \"$org\"\n"; } - - # Get the UUID of the organization from its URL - my $org_uuid = (split /\//, $vcd->{raw_login_data}->{Org}->{$org}->{href})[-1]; - - # Calculate the admin URL of the org - my $adm_org = $vcd->{api}->org_get( $vcd->{api}->{url_base} . "/admin/org/$org_uuid" ); - - # Get the array of usernames - my @users = keys %{$adm_org->{Users}[0]->{UserReference}}; - - return \@users; -$_X$; - - -ALTER FUNCTION api.get_vcloud_group_members(text, text, text, text) OWNER TO postgres; - --- --- Name: get_vlans(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION get_vlans(input_datacenter text) RETURNS SETOF network.vlans - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_datacenter IS NULL THEN - RETURN QUERY (SELECT * FROM "network"."vlans" ORDER BY "datacenter","vlan"); - ELSE - RETURN QUERY (SELECT * FROM "network"."vlans" WHERE "datacenter" = input_datacenter ORDER BY "vlan"); - END IF; - END; -$$; - - -ALTER FUNCTION api.get_vlans(input_datacenter text) OWNER TO starrs_admin; - --- --- Name: FUNCTION get_vlans(input_datacenter text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION get_vlans(input_datacenter text) IS 'Get all or a systems vlans'; - - --- --- Name: initialize(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION initialize(input_username text) RETURNS text - LANGUAGE plpgsql - AS $$ - DECLARE - Level TEXT; - BEGIN - -- Get level - IF api.get_site_configuration('USER_PRIVILEGE_SOURCE') ~* 'ldap' THEN - SELECT api.get_ldap_user_level(input_username) INTO Level; - ELSEIF api.get_site_configuration('USER_PRIVILEGE_SOURCE') ~* 'ad' THEN - SELECT api.get_ad_user_level(input_username) INTO Level; - ELSE - SELECT api.get_local_user_level(input_username) INTO Level; - END IF; - - IF Level='NONE' THEN - RAISE EXCEPTION 'Could not identify "%".',input_username; - END IF; - - -- Create privilege table - DROP TABLE IF EXISTS "user_privileges"; - - CREATE TEMPORARY TABLE "user_privileges" - (username text NOT NULL,privilege text NOT NULL, - allow boolean NOT NULL DEFAULT false); - - -- Populate privileges - INSERT INTO "user_privileges" VALUES (input_username,'USERNAME',TRUE); - INSERT INTO "user_privileges" VALUES (input_username,'ADMIN',FALSE); - INSERT INTO "user_privileges" VALUES (input_username,'PROGRAM',FALSE); - INSERT INTO "user_privileges" VALUES (input_username,'USER',FALSE); - ALTER TABLE "user_privileges" ALTER COLUMN "username" SET DEFAULT api.get_current_user(); - - -- Set level - UPDATE "user_privileges" SET "allow" = TRUE WHERE "privilege" ~* Level; - - RETURN 'Greetings '||lower(Level)||'!'; - END; -$$; - - -ALTER FUNCTION api.initialize(input_username text) OWNER TO starrs_admin; - --- --- Name: FUNCTION initialize(input_username text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION initialize(input_username text) IS 'Setup user access to the database'; - - --- --- Name: ip_arp(inet); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION ip_arp(input_address inet) RETURNS macaddr - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN (SELECT "mac" FROM "systems"."interface_addresses" WHERE "address" = input_address); - END; -$$; - - -ALTER FUNCTION api.ip_arp(input_address inet) OWNER TO starrs_admin; - --- --- Name: FUNCTION ip_arp(input_address inet); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION ip_arp(input_address inet) IS 'Get the MAC address assiciated with an IP address'; - - --- --- Name: ip_in_subnet(inet, cidr); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION ip_in_subnet(input_address inet, input_subnet cidr) RETURNS boolean - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_address << input_subnet THEN - RETURN TRUE; - ELSE - RETURN FALSE; - END IF; - END; -$$; - - -ALTER FUNCTION api.ip_in_subnet(input_address inet, input_subnet cidr) OWNER TO starrs_admin; - --- --- Name: FUNCTION ip_in_subnet(input_address inet, input_subnet cidr); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION ip_in_subnet(input_address inet, input_subnet cidr) IS 'True or False if an address is contained within a given subnet'; - - --- --- Name: ip_is_dynamic(inet); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION ip_is_dynamic(input_address inet) RETURNS boolean - LANGUAGE plpgsql - AS $$ - BEGIN - IF input_address << cidr((SELECT api.get_site_configuration('DYNAMIC_SUBNET'))) THEN - RETURN TRUE; - ELSE - RETURN FALSE; - END IF; - END; -$$; - - -ALTER FUNCTION api.ip_is_dynamic(input_address inet) OWNER TO starrs_admin; - --- --- Name: modify_availability_zone(text, text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_availability_zone(input_old_datacenter text, input_old_zone text, input_field text, input_new_value text) RETURNS SETOF systems.availability_zones - LANGUAGE plpgsql - AS $_$ - BEGIN - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - RAISE EXCEPTION 'Permission to edit availability zone denied. You are not admin'; - END IF; - - -- Check allowed fields - IF input_field !~* 'datacenter|zone|comment' THEN - RAISE EXCEPTION 'Invalid field % specified',input_field; - END IF; - - -- Update record - - EXECUTE 'UPDATE "systems"."availability_zones" SET ' || quote_ident($3) || ' = $4, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "datacenter" = $1 AND "zone" = $2' - USING input_old_datacenter, input_old_zone, input_field, input_new_value; - - -- Done - - PERFORM api.syslog('modify_availability_zone:"'||input_old_datacenter||'","'||input_old_zone||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'zone' THEN - RETURN QUERY (SELECT * FROM "systems"."availability_zones" WHERE "datacenter" = input_old_datacenter AND "zone" = input_new_value); - ELSEIF input_field ~* 'datacenter' THEN - RETURN QUERY (SELECT * FROM "systems"."availability_zones" WHERE "datacenter" = input_new_value AND "zone" = input_old_zone); - ELSE - RETURN QUERY (SELECT * FROM "systems"."availability_zones" WHERE "datacenter" = input_old_datacenter AND "zone" = input_old_zone); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_availability_zone(input_old_datacenter text, input_old_zone text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_availability_zone(input_old_datacenter text, input_old_zone text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_availability_zone(input_old_datacenter text, input_old_zone text, input_field text, input_new_value text) IS 'modify a availability_zone'; - - --- --- Name: modify_datacenter(text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_datacenter(input_old_name text, input_field text, input_new_value text) RETURNS SETOF systems.datacenters - LANGUAGE plpgsql - AS $_$ - BEGIN - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - RAISE EXCEPTION 'Permission to edit address % denied. You are not admin'; - END IF; - - -- Check allowed fields - IF input_field !~* 'datacenter|comment' THEN - RAISE EXCEPTION 'Invalid field % specified',input_field; - END IF; - - -- Update record - - EXECUTE 'UPDATE "systems"."datacenters" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "datacenter" = $1' - USING input_old_name, input_field, input_new_value; - - -- Done - - PERFORM api.syslog('modify_datacenter:"'||input_old_name||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'datacenter' THEN - RETURN QUERY (SELECT * FROM "systems"."datacenters" WHERE "datacenter" = input_new_value); - ELSE - RETURN QUERY (SELECT * FROM "systems"."datacenters" WHERE "datacenter" = input_old_name); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_datacenter(input_old_name text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_datacenter(input_old_name text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_datacenter(input_old_name text, input_field text, input_new_value text) IS 'modify a datacenter'; - - --- --- Name: modify_dhcp_class(text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_dhcp_class(input_old_class text, input_field text, input_new_value text) RETURNS SETOF dhcp.classes - LANGUAGE plpgsql - AS $_$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - RAISE EXCEPTION 'Permission to modify dhcp class denied for %. Not admin.',api.get_current_user(); - END IF; - - -- Check allowed fields - IF input_field !~* 'class|comment' THEN - RAISE EXCEPTION 'Invalid field specified (%)',input_field; - END IF; - - -- Validate class name - IF input_field !~* 'class' THEN - input_new_value := api.validate_nospecial(input_new_value); - END IF; - - -- Update record - EXECUTE 'UPDATE "dhcp"."classes" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "class" = $1' - USING input_old_class, input_field, input_new_value; - - -- Done - PERFORM api.syslog('modify_dhcp_class:"'||input_old_class||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'class' THEN - RETURN QUERY (SELECT * FROM "dhcp"."classes" WHERE "class" = input_new_value); - ELSE - RETURN QUERY (SELECT * FROM "dhcp"."classes" WHERE "class" = input_old_class); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_dhcp_class(input_old_class text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_dhcp_class(input_old_class text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_dhcp_class(input_old_class text, input_field text, input_new_value text) IS 'Modify a field of a DHCP setting'; - - --- --- Name: modify_dhcp_class_option(text, text, text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_dhcp_class_option(input_old_class text, input_old_option text, input_old_value text, input_field text, input_new_value text) RETURNS SETOF dhcp.class_options - LANGUAGE plpgsql - AS $_$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - RAISE EXCEPTION 'Permission to modify dhcp class option denied for %. Not admin.',api.get_current_user(); - END IF; - - -- Check allowed fields - IF input_field !~* 'class|option|value' THEN - RAISE EXCEPTION 'Invalid field specified (%)',input_field; - END IF; - - -- Update record - EXECUTE 'UPDATE "dhcp"."class_options" SET ' || quote_ident($4) || ' = $5, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "class" = $1 AND "option" = $2 AND "value" = $3' - USING input_old_class, input_old_option, input_old_value, input_field, input_new_value; - - -- Done - PERFORM api.syslog('modify_dhcp_class_option:"'||input_old_class||'","'||input_old_option||'","'||input_old_value||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'class' THEN - RETURN QUERY (SELECT * FROM "dhcp"."class_options" - WHERE "class" = input_new_value AND "option" = input_old_option AND "value" = input_old_value); - ELSIF input_field ~* 'option' THEN - RETURN QUERY (SELECT * FROM "dhcp"."class_options" - WHERE "class" = input_old_class AND "option" = input_new_value AND "value" = input_old_value); - ELSE - RETURN QUERY (SELECT * FROM "dhcp"."class_options" - WHERE "class" = input_old_class AND "option" = input_old_option AND "value" = input_new_value); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_dhcp_class_option(input_old_class text, input_old_option text, input_old_value text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_dhcp_class_option(input_old_class text, input_old_option text, input_old_value text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_dhcp_class_option(input_old_class text, input_old_option text, input_old_value text, input_field text, input_new_value text) IS 'Modify a field of a DHCP class option'; - - --- --- Name: modify_dhcp_global_option(text, text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_dhcp_global_option(input_old_option text, input_old_value text, input_field text, input_new_value text) RETURNS SETOF dhcp.global_options - LANGUAGE plpgsql - AS $_$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - RAISE EXCEPTION 'Permission to modify dhcp global option denied for %. Not admin.',api.get_current_user(); - END IF; - - -- Check allowed fields - IF input_field !~* 'option|value' THEN - RAISE EXCEPTION 'Invalid field specified (%)',input_field; - END IF; - - -- Update record - EXECUTE 'UPDATE "dhcp"."global_options" SET ' || quote_ident($3) || ' = $4, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "option" = $1 AND "value" = $2' - USING input_old_option, input_old_value, input_field, input_new_value; - - -- Done - PERFORM api.syslog('modify_dhcp_global_option:"'||input_old_option||'","'||input_old_value||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'option' THEN - RETURN QUERY (SELECT * FROM "dhcp"."global_options" - WHERE "option" = input_new_value AND "value" = input_old_value); - ELSE - RETURN QUERY (SELECT * FROM "dhcp"."global_options" - WHERE "option" = input_old_option AND "value" = input_new_value); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_dhcp_global_option(input_old_option text, input_old_value text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_dhcp_global_option(input_old_option text, input_old_value text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_dhcp_global_option(input_old_option text, input_old_value text, input_field text, input_new_value text) IS 'Modify a field of a DHCP global option'; - - --- --- Name: modify_dhcp_range_option(text, text, text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_dhcp_range_option(input_old_range text, input_old_option text, input_old_value text, input_field text, input_new_value text) RETURNS SETOF dhcp.range_options - LANGUAGE plpgsql - AS $_$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - RAISE EXCEPTION 'Permission to modify dhcp range option denied for %. Not admin.',api.get_current_user(); - END IF; - - -- Check allowed fields - IF input_field !~* 'name|option|value' THEN - RAISE EXCEPTION 'Invalid field specified (%)',input_field; - END IF; - - -- Check if range is marked for DHCP - IF input_field ~* 'name' THEN - IF (SELECT "use" FROM "ip"."ranges" WHERE "name" = input_new_value) !~* 'ROAM' THEN - RAISE EXCEPTION 'Range % is not marked for DHCP configuration',input_new_value; - END IF; - END IF; - - -- Update record - EXECUTE 'UPDATE "dhcp"."range_options" SET ' || quote_ident($4) || ' = $5, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "name" = $1 AND "option" = $2 AND "value" = $3' - USING input_old_range, input_old_option, input_old_value, input_field, input_new_value; - - -- Done - PERFORM api.syslog('modify_dhcp_range_option:"'||input_old_range||'","'||input_old_option||'","'||input_old_value||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'name' THEN - RETURN QUERY (SELECT * FROM "dhcp"."range_options" - WHERE "name" = input_new_value AND "option" = input_old_option AND "value" = input_old_value); - ELSIF input_field ~* 'option' THEN - RETURN QUERY (SELECT * FROM "dhcp"."range_options" - WHERE "name" = input_old_range AND "option" = input_new_value AND "value" = input_old_value); - ELSE - RETURN QUERY (SELECT * FROM "dhcp"."range_options" - WHERE "name" = input_old_range AND "option" = input_old_option AND "value" = input_new_value); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_dhcp_range_option(input_old_range text, input_old_option text, input_old_value text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_dhcp_range_option(input_old_range text, input_old_option text, input_old_value text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_dhcp_range_option(input_old_range text, input_old_option text, input_old_value text, input_field text, input_new_value text) IS 'Modify a field of a DHCP range option'; - - --- --- Name: modify_dhcp_subnet_option(cidr, text, text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_dhcp_subnet_option(input_old_subnet cidr, input_old_option text, input_old_value text, input_field text, input_new_value text) RETURNS SETOF dhcp.subnet_options - LANGUAGE plpgsql - AS $_$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - RAISE EXCEPTION 'Permission to modify dhcp subnet option denied for %. Not admin.',api.get_current_user(); - END IF; - - -- Check allowed fields - IF input_field !~* 'subnet|option|value' THEN - RAISE EXCEPTION 'Invalid field specified (%)',input_field; - END IF; - - -- Update record - EXECUTE 'UPDATE "dhcp"."subnet_options" SET ' || quote_ident($4) || ' = $5, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "subnet" = $1 AND "option" = $2 AND "value" = $3' - USING input_old_subnet, input_old_option, input_old_value, input_field, input_new_value; - - -- Done - PERFORM api.syslog('modify_dhcp_subnet_option:"'||input_old_subnet||'","'||input_old_option||'","'||input_old_value||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'subnet' THEN - RETURN QUERY (SELECT * FROM "dhcp"."subnet_options" - WHERE "subnet" = input_new_value AND "option" = input_old_option AND "value" = input_old_value); - ELSIF input_field ~* 'option' THEN - RETURN QUERY (SELECT * FROM "dhcp"."subnet_options" - WHERE "subnet" = input_old_subnet AND "option" = input_new_value AND "value" = input_old_value); - ELSE - RETURN QUERY (SELECT * FROM "dhcp"."subnet_options" - WHERE "subnet" = input_old_subnet AND "option" = input_old_option AND "value" = input_new_value); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_dhcp_subnet_option(input_old_subnet cidr, input_old_option text, input_old_value text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_dhcp_subnet_option(input_old_subnet cidr, input_old_option text, input_old_value text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_dhcp_subnet_option(input_old_subnet cidr, input_old_option text, input_old_value text, input_field text, input_new_value text) IS 'Modify a field of a DHCP subnet option'; - - --- --- Name: modify_dns_address(inet, text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_dns_address(input_old_address inet, input_old_zone text, input_field text, input_new_value text) RETURNS SETOF dns.a - LANGUAGE plpgsql - AS $_$ - BEGIN - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF (SELECT "write" FROM api.get_system_permissions(api.get_interface_address_system(input_old_address))) IS FALSE THEN - RAISE EXCEPTION 'Permission denied'; - END IF; - -- Shared zone - IF (SELECT "shared" FROM "dns"."zones" WHERE "zone" = input_old_zone) IS FALSE THEN - RAISE EXCEPTION 'Zone is not shared and you are not admin'; - END IF; - END IF; - - -- Check allowed fields - IF input_field !~* 'hostname|zone|address|owner|ttl' THEN - RAISE EXCEPTION 'Invalid field % specified',input_field; - END IF; - - IF input_field ~* 'ttl' THEN - -- User can only specify TTL if address is static - IF (SELECT "config" FROM "systems"."interface_addresses" WHERE "address" = input_old_address) !~* 'static' AND input_new_value::integer != (SELECT "value"::integer/2 AS "ttl" FROM "dhcp"."subnet_options" WHERE "option"='default-lease-time' AND "subnet" >> input_old_address) THEN - RAISE EXCEPTION 'You can only specify a TTL other than the default if your address is configured statically'; - END IF; - END IF; - - IF api.get_current_user_level() !~* 'ADMIN' THEN - -- Owner - IF input_field ~* 'owner' THEN - -- Different owner - IF (SELECT "owner" FROM "dns"."a" WHERE "address" = input_old_address AND "zone" = input_zone) != input_new_value THEN - RAISE EXCEPTION 'Only admins can define a different owner (%).',input_new_value; - END IF; - END IF; - END IF; - - -- Lower - IF input_field ~* 'hostname' THEN - input_new_value := lower(input_new_value); - END IF; - - -- Update record - - IF input_field ~* 'address' THEN - EXECUTE 'UPDATE "dns"."a" SET ' || quote_ident($3) || ' = $4, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "address" = $1 AND "zone" = $2' - USING input_old_address, input_old_zone, input_field, inet(input_new_value); - ELSIF input_field ~* 'ttl' THEN - EXECUTE 'UPDATE "dns"."a" SET ' || quote_ident($3) || ' = $4, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "address" = $1 AND "zone" = $2' - USING input_old_address, input_old_zone, input_field, cast(input_new_value as int); - ELSE - EXECUTE 'UPDATE "dns"."a" SET ' || quote_ident($3) || ' = $4, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "address" = $1 AND "zone" = $2' - USING input_old_address, input_old_zone, input_field, input_new_value; - END IF; - - -- Done - PERFORM api.syslog('modify_dns_address:"'||input_old_address||'","'||input_old_zone||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'address' THEN - RETURN QUERY (SELECT * FROM "dns"."a" WHERE "address" = inet(input_new_value) AND "zone" = input_old_zone); - ELSEIF input_field ~* 'zone' THEN - RETURN QUERY (SELECT * FROM "dns"."a" WHERE "address" = input_old_address AND "zone" = input_new_value); - ELSE - RETURN QUERY (SELECT * FROM "dns"."a" WHERE "address" = input_old_address AND "zone" = input_old_zone); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_dns_address(input_old_address inet, input_old_zone text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_dns_address(input_old_address inet, input_old_zone text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_dns_address(input_old_address inet, input_old_zone text, input_field text, input_new_value text) IS 'Modify an existing DNS address'; - - --- --- Name: modify_dns_cname(text, text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_dns_cname(input_old_alias text, input_old_zone text, input_field text, input_new_value text) RETURNS SETOF dns.cname - LANGUAGE plpgsql - AS $_$ - BEGIN - - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - -- Shared zone - IF (SELECT "shared" FROM "dns"."zones" WHERE "zone" = input_old_zone) IS FALSE THEN - RAISE EXCEPTION 'Zone is not shared and you are not admin'; - END IF; - -- System owner - IF (SELECT "write" FROM api.get_system_permissions(api.get_interface_address_system((SELECT "address" FROM "dns"."cname" WHERE "alias" = input_old_alias AND "zone" = input_old_zone)))) IS FALSE THEN - RAISE EXCEPTION 'Permission denied'; - END IF; - -- Another owner - IF input_field !~* 'owner' THEN - IF input_new_value != api.get_current_user() THEN - RAISE EXCEPTION 'You specified another owner when you are not an admin'; - END IF; - END IF; - END IF; - - -- Check allowed fields - IF input_field !~* 'hostname|zone|alias|owner|ttl' THEN - RAISE EXCEPTION 'Invalid field % specified',input_field; - END IF; - - -- Lower - IF input_field ~* 'hostname|alias' THEN - input_new_value := lower(input_new_value); - END IF; - - -- Check for in use - IF input_field ~* 'alias' THEN - IF (SELECT api.check_dns_hostname(input_new_value, input_zone)) IS TRUE THEN - RAISE EXCEPTION 'Record with this hostname and zone already exists'; - END IF; - END IF; - - -- Update record - IF input_field ~* 'ttl' THEN - EXECUTE 'UPDATE "dns"."cname" SET ' || quote_ident($3) || ' = $4, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "alias" = $1 AND "zone" = $2' - USING input_old_alias, input_old_zone, input_field, cast(input_new_value as int); - ELSEIF input_field ~* 'hostname' THEN - EXECUTE 'UPDATE "dns"."cname" SET ' || quote_ident($3) || ' = $4, - date_modified = localtimestamp(0), last_modifier = api.get_current_user(), address = (SELECT "address" FROM "dns"."a" WHERE "hostname" = $4 AND "zone" = $2) - WHERE "alias" = $1 AND "zone" = $2' - USING input_old_alias, input_old_zone, input_field, input_new_value; - ELSE - EXECUTE 'UPDATE "dns"."cname" SET ' || quote_ident($3) || ' = $4, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "alias" = $1 AND "zone" = $2' - USING input_old_alias, input_old_zone, input_field, input_new_value; - END IF; - - -- Done - PERFORM api.syslog('modify_dns_cname:"'||input_old_alias||'","'||input_old_zone||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'alias' THEN - RETURN QUERY (SELECT * FROM "dns"."cname" WHERE "alias" = input_new_value AND "zone" = input_old_zone); - ELSEIF input_field ~* 'zone' THEN - RETURN QUERY (SELECT * FROM "dns"."cname" WHERE "alias" = input_old_alias AND "zone" = input_new_value); - ELSE - RETURN QUERY (SELECT * FROM "dns"."cname" WHERE "alias" = input_old_alias AND "zone" = input_old_zone); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_dns_cname(input_old_alias text, input_old_zone text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_dns_cname(input_old_alias text, input_old_zone text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_dns_cname(input_old_alias text, input_old_zone text, input_field text, input_new_value text) IS 'Modify an existing DNS CNAME record'; - - --- --- Name: modify_dns_key(text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_dns_key(input_old_keyname text, input_field text, input_new_value text) RETURNS SETOF dns.keys - LANGUAGE plpgsql - AS $_$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "dns"."keys" WHERE "keyname" = input_old_keyname) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission to edit key % denied. You are not owner',input_old_keyname; - END IF; - - IF input_field ~* 'owner' AND input_new_value != api.get_current_user() THEN - RAISE EXCEPTION 'Only administrators can define a different owner (%).',input_new_value; - END IF; - END IF; - - -- Check allowed fields - IF input_field !~* 'keyname|key|comment|owner|enctype' THEN - RAISE EXCEPTION 'Invalid field % specified',input_field; - END IF; - - -- Validate input - IF input_field ~* 'keyname' THEN - input_new_value := api.validate_nospecial(input_new_value); - END IF; - - -- Update record - EXECUTE 'UPDATE "dns"."keys" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "keyname" = $1' - USING input_old_keyname, input_field, input_new_value; - - -- Done - PERFORM api.syslog('modify_dns_key:"'||input_old_keyname||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'keyname' THEN - RETURN QUERY (SELECT * FROM "dns"."keys" WHERE "keyname" = input_new_value); - ELSE - RETURN QUERY (SELECT * FROM "dns"."keys" WHERE "keyname" = input_old_keyname); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_dns_key(input_old_keyname text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_dns_key(input_old_keyname text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_dns_key(input_old_keyname text, input_field text, input_new_value text) IS 'Modify an existing DNS key'; - - --- --- Name: modify_dns_mailserver(text, text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_dns_mailserver(input_old_hostname text, input_old_zone text, input_field text, input_new_value text) RETURNS SETOF dns.mx - LANGUAGE plpgsql - AS $_$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - -- Zone owner - IF (SELECT "owner" FROM "dns"."zones" WHERE "zone" = input_old_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied'; - END IF; - -- You own the system - IF (SELECT "write" FROM api.get_system_permissions(api.get_interface_address_system(input_old_address))) IS FALSE THEN - RAISE EXCEPTION 'Permission denied'; - END IF; - END IF; - - -- Check allowed fields - IF input_field !~* 'hostname|zone|preference|owner|ttl' THEN - RAISE EXCEPTION 'Invalid field % specified',input_field; - END IF; - - -- Lower - IF input_field ~* 'hostname' THEN - input_new_value := lower(input_new_value); - END IF; - - -- Update record - - IF input_field ~* 'preference|ttl' THEN - EXECUTE 'UPDATE "dns"."mx" SET ' || quote_ident($3) || ' = $4, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "hostname" = $1 AND "zone" = $2' - USING input_old_hostname, input_old_zone, input_field, cast(input_new_value as int); - ELSEIF input_field ~* 'hostname' THEN - EXECUTE 'UPDATE "dns"."mx" SET ' || quote_ident($3) || ' = $4, - date_modified = localtimestamp(0), last_modifier = api.get_current_user(), address = (SELECT "address" FROM "dns"."a" WHERE "hostname" = $4 AND "zone" = $2) - WHERE "hostname" = $1 AND "zone" = $2' - USING input_old_hostname, input_old_zone, input_field, input_new_value; - ELSE - EXECUTE 'UPDATE "dns"."mx" SET ' || quote_ident($3) || ' = $4, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "hostname" = $1 AND "zone" = $2' - USING input_old_hostname, input_old_zone, input_field, input_new_value; - END IF; - - -- Done - PERFORM api.syslog('modify_dns_mailserver:"'||input_old_hostname||'","'||input_old_zone||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'hostname' THEN - RETURN QUERY (SELECT * FROM "dns"."mx" WHERE "hostname" = input_new_value AND "zone" = input_old_zone); - ELSEIF input_field ~* 'zone' THEN - RETURN QUERY (SELECT * FROM "dns"."mx" WHERE "hostname" = input_old_hostname AND "zone" = input_new_value); - ELSE - RETURN QUERY (SELECT * FROM "dns"."mx" WHERE "hostname" = input_old_hostname AND "zone" = input_old_zone); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_dns_mailserver(input_old_hostname text, input_old_zone text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_dns_mailserver(input_old_hostname text, input_old_zone text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_dns_mailserver(input_old_hostname text, input_old_zone text, input_field text, input_new_value text) IS 'Modify an existing DNS MX record'; - - --- --- Name: modify_dns_ns(text, text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_dns_ns(input_old_zone text, input_old_nameserver text, input_field text, input_new_value text) RETURNS SETOF dns.ns - LANGUAGE plpgsql - AS $_$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - -- You own the zone - IF (SELECT "owner" FROM "dns"."zones" WHERE "zone" = input_old_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission to edit nameserver (%.%) denied. You are not owner',input_old_nameserver,input_old_zone; - END IF; - END IF; - - -- Check allowed fields - IF input_field !~* 'nameserver|zone|ttl|address' THEN - RAISE EXCEPTION 'Invalid field % specified',input_field; - END IF; - - -- Lower - IF input_field ~* 'nameserver' THEN - input_new_value := lower(input_new_value); - END IF; - - -- Update record - IF input_field ~* 'ttl' THEN - EXECUTE 'UPDATE "dns"."ns" SET ' || quote_ident($3) || ' = $4, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "zone" = $1 AND "nameserver" = $2' - USING input_old_zone, input_old_nameserver, input_field, cast(input_new_value as int); - - -- Update TTLs of other zone records since they all need to be the same - UPDATE "dns"."ns" SET "ttl" = cast(input_new_value as int) WHERE "zone" = input_old_zone; - - ELSEIF input_field ~* 'address' THEN - EXECUTE 'UPDATE "dns"."ns" SET ' || quote_ident($3) || ' = $4, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "zone" = $1 AND "nameserver" = $2' - USING input_old_zone, input_old_nameserver, input_field, cast(input_new_value as inet); - ELSE - EXECUTE 'UPDATE "dns"."ns" SET ' || quote_ident($3) || ' = $4, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "zone" = $1 AND "nameserver" = $2' - USING input_old_zone, input_old_nameserver, input_field, input_new_value; - END IF; - - -- Done - PERFORM api.syslog('modify_dns_ns:"'||input_old_zone||'","'||input_old_nameserver||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'input_old_zone' THEN - RETURN QUERY (SELECT * FROM "dns"."ns" WHERE "zone" = input_new_value AND "nameserver" = input_old_nameserver); - ELSEIF input_field ~* 'nameserver' THEN - RETURN QUERY (SELECT * FROM "dns"."ns" WHERE "zone" = input_old_zone AND "nameserver" = input_new_value); - ELSE - RETURN QUERY (SELECT * FROM "dns"."ns" WHERE "zone" = input_old_zone AND "nameserver" = input_old_nameserver); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_dns_ns(input_old_zone text, input_old_nameserver text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_dns_ns(input_old_zone text, input_old_nameserver text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_dns_ns(input_old_zone text, input_old_nameserver text, input_field text, input_new_value text) IS 'Modify an existing DNS NS record'; - - --- --- Name: modify_dns_soa(text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_dns_soa(input_old_zone text, input_field text, input_new_value text) RETURNS SETOF dns.soa - LANGUAGE plpgsql - AS $_$ - BEGIN - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "dns"."zones" WHERE "zone" = input_old_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission to edit SOA % denied. You are not owner',input_old_zone; - END IF; - END IF; - - -- Check allowed fields - IF input_field !~* 'zone|ttl|nameserver|contact|serial|refresh|retry|expire|minimum' THEN - RAISE EXCEPTION 'Invalid field % specified',input_field; - END IF; - - -- Validate - IF input_field ~* 'contact' THEN - IF api.validate_soa_contact(input_new_value) IS FALSE THEN - RAISE EXCEPTION 'Invalid SOA contact given (%)',input_contact; - END IF; - END IF; - - -- Update record - IF input_field ~* 'ttl|refresh|retry|expire|minimum' THEN - EXECUTE 'UPDATE "dns"."soa" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "zone" = $1' - USING input_old_zone, input_field, cast(input_new_value as integer); - ELSE - EXECUTE 'UPDATE "dns"."soa" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "zone" = $1' - USING input_old_zone, input_field, input_new_value; - END IF; - - -- Done - PERFORM api.syslog('modify_dns_soa:"'||input_old_zone||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'zone' THEN - RETURN QUERY (SELECT * FROM "dns"."soa" WHERE "zone" = input_new_value); - ELSE - RETURN QUERY (SELECT * FROM "dns"."soa" WHERE "zone" = input_old_zone); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_dns_soa(input_old_zone text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_dns_soa(input_old_zone text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_dns_soa(input_old_zone text, input_field text, input_new_value text) IS 'Modify an existing DNS SOA record'; - - --- --- Name: modify_dns_srv(text, text, integer, integer, integer, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_dns_srv(input_old_alias text, input_old_zone text, input_old_priority integer, input_old_weight integer, input_old_port integer, input_field text, input_new_value text) RETURNS SETOF dns.srv - LANGUAGE plpgsql - AS $_$ - BEGIN - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - -- You own the system - IF (SELECT "write" FROM api.get_system_permissions(api.get_interface_address_system((SELECT "address" FROM "dns"."srv" WHERE "alias" = input_old_alias AND "zone" = input_old_zone AND "priority" = input_old_priority AND "weight" = input_old_weight AND "port" = input_old_port)))) IS FALSE THEN - RAISE EXCEPTION 'Permission denied'; - END IF; - -- You own the zone - IF (SELECT "owner" FROM "dns"."zones" WHERE "zone" = input_old_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission to edit denied: You are not zone owner'; - END IF; - END IF; - - -- Check allowed fields - IF input_field !~* 'hostname|zone|alias|owner|ttl|priority|weight|port' THEN - RAISE EXCEPTION 'Invalid field % specified',input_field; - END IF; - - -- Lower - IF input_field ~* 'hostname|alias' THEN - input_new_value := lower(input_new_value); - END IF; - - -- Update record - IF input_field ~* 'ttl|priority|weight|port' THEN - EXECUTE 'UPDATE "dns"."srv" SET ' || quote_ident($6) || ' = $7, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "alias" = $1 AND "zone" = $2 AND "priority" = $3 AND "weight" = $4 AND "port" = $5' - USING input_old_alias, input_old_zone, input_old_priority, input_old_weight, input_old_port, input_field, cast(input_new_value as int); - ELSEIF input_field ~* 'hostname' THEN - RAISE EXCEPTION 'test'; - EXECUTE 'UPDATE "dns"."srv" SET ' || quote_ident($6) || ' = $7, - date_modified = localtimestamp(0), last_modifier = api.get_current_user(), address = (SELECT "address" FROM "dns"."a" WHERE "hostname" = $7 AND "zone" = $2) - WHERE "alias" = $1 AND "zone" = $2 AND "priority" = $3 AND "weight" = $4 AND "port" = $5' - USING input_old_alias, input_old_zone, input_old_priority, input_old_weight, input_old_port, input_field, input_new_value; - ELSE - EXECUTE 'UPDATE "dns"."srv" SET ' || quote_ident($6) || ' = $7, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "alias" = $1 AND "zone" = $2 AND "priority" = $3 AND "weight" = $4 AND "port" = $5' - USING input_old_alias, input_old_zone, input_old_priority, input_old_weight, input_old_port, input_field, input_new_value; - END IF; - - -- Done - PERFORM api.syslog('modify_dns_srv:"'||input_old_alias||'","'||input_old_zone||'","'||input_old_priority||'","'||input_old_weight||'","'||input_old_port||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'alias' THEN - RETURN QUERY (SELECT * FROM "dns"."srv" - WHERE "alias" = input_new_value AND "zone" = input_old_zone AND "priority" = input_old_priority AND "weight" = input_old_weight AND "port" = input_old_port); - ELSEIF input_field ~* 'zone' THEN - RETURN QUERY (SELECT * FROM "dns"."srv" - WHERE "alias" = input_old_alias AND "zone" = input_new_value AND "priority" = input_old_priority AND "weight" = input_old_weight AND "port" = input_old_port); - ELSEIF input_field ~* 'priority' THEN - RETURN QUERY (SELECT * FROM "dns"."srv" - WHERE "alias" = input_old_alias AND "zone" = input_old_zone AND "priority" = input_new_value::integer AND "weight" = input_old_weight AND "port" = input_old_port); - ELSEIF input_field ~* 'weight' THEN - RETURN QUERY (SELECT * FROM "dns"."srv" - WHERE "alias" = input_old_alias AND "zone" = input_old_zone AND "priority" = input_old_priority AND "weight" = input_new_value::integer AND "port" = input_old_port); - ELSEIF input_field ~* 'port' THEN - RETURN QUERY (SELECT * FROM "dns"."srv" - WHERE "alias" = input_old_alias AND "zone" = input_old_zone AND "priority" = input_old_priority AND "weight" = input_old_weight AND "port" = input_new_value::integer); - ELSE - RETURN QUERY (SELECT * FROM "dns"."srv" - WHERE "alias" = input_old_alias AND "zone" = input_old_zone AND "priority" = input_old_priority AND "weight" = input_old_weight AND "port" = input_old_port); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_dns_srv(input_old_alias text, input_old_zone text, input_old_priority integer, input_old_weight integer, input_old_port integer, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_dns_srv(input_old_alias text, input_old_zone text, input_old_priority integer, input_old_weight integer, input_old_port integer, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_dns_srv(input_old_alias text, input_old_zone text, input_old_priority integer, input_old_weight integer, input_old_port integer, input_field text, input_new_value text) IS 'Modify an existing DNS SRV record'; - - --- --- Name: modify_dns_txt(text, text, text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_dns_txt(input_old_hostname text, input_old_zone text, input_old_text text, input_field text, input_new_value text) RETURNS SETOF dns.txt - LANGUAGE plpgsql - AS $_$ - BEGIN - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - -- Record owner - IF (SELECT "owner" FROM "dns"."txt" WHERE "hostname" = input_old_hostname AND "zone" = input_old_zone AND "text" = input_old_text) != api.get_current_user() THEN - RAISE EXCEPTION 'You are not the record owner'; - END IF; - -- Zone owner - IF (SELECT "owner" FROM "dns"."zones" WHERE "zone" = input_old_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'You are not the owner of the zone or an admin'; - END IF; - END IF; - - -- Check allowed fields - IF input_field !~* 'hostname|zone|text|owner|ttl' THEN - RAISE EXCEPTION 'Invalid field % specified',input_field; - END IF; - - -- Lower - IF input_new_value ~* 'hostname' THEN - input_new_value := lower(input_new_value); - END IF; - - -- Update record - IF input_field ~* 'ttl' THEN - EXECUTE 'UPDATE "dns"."txt" SET ' || quote_ident($4) || ' = $5, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "hostname" = $1 AND "zone" = $2 AND "text" = $3' - USING input_old_hostname, input_old_zone, input_old_text, input_field, cast(input_new_value as int); - ELSE - EXECUTE 'UPDATE "dns"."txt" SET ' || quote_ident($4) || ' = $5, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "hostname" = $1 AND "zone" = $2 AND "text" = $3' - USING input_old_hostname, input_old_zone, input_old_text, input_field, input_new_value; - END IF; - - -- Done - PERFORM api.syslog('modify_dns_txt:"'||input_old_hostname||'","'||input_old_zone||'","'||input_old_text||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'hostname' THEN - RETURN QUERY (SELECT * FROM "dns"."txt" WHERE "hostname" = input_new_value AND "zone" = input_old_zone AND "text" = input_old_text); - ELSEIF input_field ~* 'zone' THEN - RETURN QUERY (SELECT * FROM "dns"."txt" WHERE "hostname" = input_old_hostname AND "zone" = input_new_value AND "text" = input_old_text); - ELSEIF input_field ~* 'text' THEN - RETURN QUERY (SELECT * FROM "dns"."txt" WHERE "hostname" = input_old_hostname AND "zone" = input_old_zone AND "text" = input_new_value); - ELSE - RETURN QUERY (SELECT * FROM "dns"."txt" WHERE "hostname" = input_old_hostname AND "zone" = input_old_zone AND "text" = input_old_text); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_dns_txt(input_old_hostname text, input_old_zone text, input_old_text text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_dns_txt(input_old_hostname text, input_old_zone text, input_old_text text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_dns_txt(input_old_hostname text, input_old_zone text, input_old_text text, input_field text, input_new_value text) IS 'Modify an existing DNS TXT record'; - - --- --- Name: modify_dns_zone(text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_dns_zone(input_old_zone text, input_field text, input_new_value text) RETURNS SETOF dns.zones - LANGUAGE plpgsql - AS $_$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "dns"."zones" WHERE "zone" = input_old_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission to edit zone % denied. You are not owner',input_old_zone; - END IF; - - IF input_field ~* 'owner' AND input_new_value != api.get_current_user() THEN - RAISE EXCEPTION 'Only administrators can define a different owner (%).',input_new_value; - END IF; - END IF; - - -- Check allowed fields - IF input_field !~* 'zone|forward|keyname|owner|comment|shared|ddns' THEN - RAISE EXCEPTION 'Invalid field % specified',input_field; - END IF; - - -- Update record - IF input_field ~* 'forward|shared|ddns' THEN - EXECUTE 'UPDATE "dns"."zones" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "zone" = $1' - USING input_old_zone, input_field, bool(input_new_value); - ELSE - EXECUTE 'UPDATE "dns"."zones" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "zone" = $1' - USING input_old_zone, input_field, input_new_value; - END IF; - - -- Done - PERFORM api.syslog('modify_dns_zone:"'||input_old_zone||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'zone' THEN - RETURN QUERY (SELECT * FROM "dns"."zones" WHERE "zone" = input_new_value); - ELSE - RETURN QUERY (SELECT * FROM "dns"."zones" WHERE "zone" = input_old_zone); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_dns_zone(input_old_zone text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_dns_zone(input_old_zone text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_dns_zone(input_old_zone text, input_field text, input_new_value text) IS 'Modify an existing DNS zone'; - - --- --- Name: modify_dns_zone_a(text, inet, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_dns_zone_a(input_old_zone text, input_old_address inet, input_field text, input_new_value text) RETURNS SETOF dns.zone_a - LANGUAGE plpgsql - AS $_$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "dns"."zones" WHERE "zone" = input_old_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission to edit zone % denied. You are not owner',input_old_zone; - END IF; - END IF; - - -- Check allowed fields - IF input_field !~* 'zone|address|ttl' THEN - RAISE EXCEPTION 'Invalid field % specified',input_field; - END IF; - - IF input_field ~* 'address' THEN - IF input_new_value::inet << api.get_site_configuration('DYNAMIC_SUBNET')::cidr THEN - RAISE EXCEPTION 'Zone A cannot be dynamic'; - END IF; - END IF; - - - -- Update record - IF input_field ~* 'address' THEN - EXECUTE 'UPDATE "dns"."zone_a" SET ' || quote_ident($3) || ' = $4, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "zone" = $1 AND "address" = $2' - USING input_old_zone, input_old_address, input_field, inet(input_new_value); - ELSIF input_field ~* 'ttl' THEN - EXECUTE 'UPDATE "dns"."zone_a" SET ' || quote_ident($3) || ' = $4, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "zone" = $1 AND "address" = $2' - USING input_old_zone, input_old_address, input_field, cast(input_new_value as int); - ELSE - EXECUTE 'UPDATE "dns"."zone_a" SET ' || quote_ident($3) || ' = $4, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "zone" = $1 AND "address" = $2' - USING input_old_zone, input_old_address, input_field, input_new_value; - END IF; - - -- Done - PERFORM api.syslog('modify_dns_zone_a:"'||input_old_zone||'","'||input_old_address||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'zone' THEN - RETURN QUERY (SELECT * FROM "dns"."zone_a" WHERE "zone" = input_new_value AND "address" = input_old_address); - ELSEIF input_field ~* 'address' THEN - RETURN QUERY (SELECT * FROM "dns"."zone_a" WHERE "zone" = input_old_zone AND "address" = inet(input_new_value)); - ELSE - RETURN QUERY (SELECT * FROM "dns"."zone_a" WHERE "zone" = input_old_zone AND "address" = input_old_address); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_dns_zone_a(input_old_zone text, input_old_address inet, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_dns_zone_a(input_old_zone text, input_old_address inet, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_dns_zone_a(input_old_zone text, input_old_address inet, input_field text, input_new_value text) IS 'Modify an existing DNS address'; - - --- --- Name: modify_dns_zone_txt(text, text, text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_dns_zone_txt(input_old_hostname text, input_old_zone text, input_old_text text, input_field text, input_new_value text) RETURNS SETOF dns.zone_txt - LANGUAGE plpgsql - AS $_$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "dns"."zones" WHERE "zone" = input_old_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission to edit alias (%.%) denied. You are not owner',input_old_hostname,input_old_zone; - END IF; - END IF; - - -- Check allowed fields - IF input_field !~* 'hostname|zone|text|ttl' THEN - RAISE EXCEPTION 'Invalid field % specified',input_field; - END IF; - - -- Lower - IF input_zone ~* 'hostname' THEN - input_new_value := lower(input_new_value); - END IF; - - -- Update record - IF input_field ~* 'ttl' THEN - EXECUTE 'UPDATE "dns"."zone_txt" SET ' || quote_ident($4) || ' = $5, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "hostname" = $1 AND "zone" = $2 AND "text" = $3' - USING input_old_hostname, input_old_zone, input_old_text, input_field, cast(input_new_value as int); - - -- Update other zone-only records if needed - IF input_old_hostname IS NULL THEN - UPDATE "dns"."zone_txt" SET "ttl" = cast(input_new_value as int) WHERE "hostname" IS NULL AND "zone" = input_old_zone; - END IF; - ELSE - EXECUTE 'UPDATE "dns"."zone_txt" SET ' || quote_ident($4) || ' = $5, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "hostname" = $1 AND "zone" = $2 AND "text" = $3' - USING input_old_hostname, input_old_zone, input_old_text, input_field, input_new_value; - END IF; - - -- Done - IF input_field ~* 'hostname' THEN - IF input_new_value IS NULL THEN - PERFORM api.syslog('modify_dns_zone_txt:"'||input_old_hostname||'","'||input_old_zone||'","'||input_field||'"'); - RETURN QUERY (SELECT * FROM "dns"."zone_txt" WHERE "hostname" IS NULL AND "zone" = input_old_zone AND "text" = input_old_text); - ELSE - PERFORM api.syslog('modify_dns_zone_txt:"'||input_old_hostname||'","'||input_old_zone||'","'||input_field||'","'||input_new_value||'"'); - RETURN QUERY (SELECT * FROM "dns"."zone_txt" WHERE "hostname" = input_new_value AND "zone" = input_old_zone AND "text" = input_old_text); - END IF; - ELSEIF input_field ~* 'zone' THEN - IF input_old_hostname IS NULL THEN - PERFORM api.syslog('modify_dns_zone_txt:"'||input_old_zone||'","'||input_field||'","'||input_new_value||'"'); - RETURN QUERY (SELECT * FROM "dns"."zone_txt" WHERE "hostname" IS NULL AND "zone" = input_new_value AND "text" = input_old_text); - ELSE - PERFORM api.syslog('modify_dns_zone_txt:"'||input_old_hostname||'","'||input_old_zone||'","'||input_field||'","'||input_new_value||'"'); - RETURN QUERY (SELECT * FROM "dns"."zone_txt" WHERE "hostname" = input_old_hostname AND "zone" = input_new_value AND "text" = input_old_text); - END IF; - ELSEIF input_field ~* 'text' THEN - IF input_old_hostname IS NULL THEN - PERFORM api.syslog('modify_dns_zone_txt:"'||input_old_zone||'","'||input_field||'","'||input_new_value||'"'); - RETURN QUERY (SELECT * FROM "dns"."zone_txt" WHERE "hostname" IS NULL AND "zone" = input_old_zone AND "text" = input_new_value); - ELSE - PERFORM api.syslog('modify_dns_zone_txt:"'||input_old_hostname||'","'||input_old_zone||'","'||input_field||'","'||input_new_value||'"'); - RETURN QUERY (SELECT * FROM "dns"."zone_txt" WHERE "hostname" = input_old_hostname AND "zone" = input_old_zone AND "text" = input_new_value); - END IF; - ELSE - IF input_old_hostname IS NULL THEN - PERFORM api.syslog('modify_dns_zone_txt:"'||input_old_zone||'","'||input_field||'","'||input_new_value||'"'); - RETURN QUERY (SELECT * FROM "dns"."zone_txt" WHERE "hostname" IS NULL AND "zone" = input_old_zone AND "text" = input_old_text); - ELSE - PERFORM api.syslog('modify_dns_zone_txt:"'||input_old_hostname||'","'||input_old_zone||'","'||input_field||'","'||input_new_value||'"'); - RETURN QUERY (SELECT * FROM "dns"."zone_txt" WHERE "hostname" = input_old_hostname AND "zone" = input_old_zone AND "text" = input_old_text); - END IF; - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_dns_zone_txt(input_old_hostname text, input_old_zone text, input_old_text text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_dns_zone_txt(input_old_hostname text, input_old_zone text, input_old_text text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_dns_zone_txt(input_old_hostname text, input_old_zone text, input_old_text text, input_field text, input_new_value text) IS 'Modify an existing DNS zone_txt record'; - - --- --- Name: modify_domain_state(text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_domain_state(input_host text, input_domain text, input_action text) RETURNS text - LANGUAGE plpgsql - AS $$ - DECLARE - HostData RECORD; - BEGIN - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF (SELECT "owner" FROM "systems"."system" WHERE "system_name" = input_domain) THEN - RAISE EXCEPTION 'Permission denied: Not VM owner'; - END IF; - END IF; - - SELECT * INTO HostData FROM "libvirt"."hosts" WHERE "system_name" = input_host; - - RETURN api.control_libvirt_domain(HostData.uri,HostData.password,input_domain,input_action); - END; -$$; - - -ALTER FUNCTION api.modify_domain_state(input_host text, input_domain text, input_action text) OWNER TO starrs_admin; - --- --- Name: modify_group(text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_group(input_old_group text, input_field text, input_new_value text) RETURNS SETOF management.groups - LANGUAGE plpgsql - AS $_$ - BEGIN - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission denied. Only admins can modify groups'; - END IF; - - IF input_field !~* 'group|privilege|renew_interval|comment' THEN - RAISE EXCEPTION 'Invalid field specified (%)',input_field; - END IF; - - IF input_field ~* 'renew_interval' THEN - EXECUTE 'UPDATE "management"."groups" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "group" = $1' - USING input_old_group, input_field, input_new_value::interval; - ELSE - EXECUTE 'UPDATE "management"."groups" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "group" = $1' - USING input_old_group, input_field, input_new_value; - END IF; - - PERFORM api.syslog('modify_group:"'||input_old_group||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'group' THEN - RETURN QUERY (SELECT * FROM "management"."groups" WHERE "group" = input_new_value); - ELSE - RETURN QUERY (SELECT * FROM "management"."groups" WHERE "group" = input_old_group); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_group(input_old_group text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_group(input_old_group text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_group(input_old_group text, input_field text, input_new_value text) IS 'Alter a group'; - - --- --- Name: modify_group_member(text, text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_group_member(input_old_group text, input_old_user text, input_field text, input_new_value text) RETURNS SETOF management.group_members - LANGUAGE plpgsql - AS $_$ - BEGIN - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF api.get_current_user() NOT IN (SELECT * FROM api.get_group_admins(input_old_group)) THEN - RAISE EXCEPTION 'Permission denied. Only admins can modify group members'; - END IF; - END IF; - - IF input_field !~* 'group|user|privilege' THEN - RAISE EXCEPTION 'Invalid field specified (%)',input_field; - END IF; - - EXECUTE 'UPDATE "management"."group_members" SET ' || quote_ident($3) || ' = $4, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "group" = $1 AND "user" = $2' - USING input_old_group, input_old_user, input_field, input_new_value; - - PERFORM api.syslog('modify_group_member:"'||input_old_group||'","'||input_old_user||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'group' THEN - RETURN QUERY (SELECT * FROM "management"."group_members" WHERE "group" = input_new_value AND "user" = input_old_user); - ELSEIF input_field ~* 'user' THEN - RETURN QUERY (SELECT * FROM "management"."group_members" WHERE "group" = input_old_group AND "user" = input_new_value); - ELSE - RETURN QUERY (SELECT * FROM "management"."group_members" WHERE "group" = input_old_group AND "user" = input_old_user); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_group_member(input_old_group text, input_old_user text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_group_member(input_old_group text, input_old_user text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_group_member(input_old_group text, input_old_user text, input_field text, input_new_value text) IS 'Modify a group member'; - - --- --- Name: modify_group_settings(text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_group_settings(input_old_group text, input_field text, input_new_value text) RETURNS SETOF management.group_settings - LANGUAGE plpgsql - AS $_$ - BEGIN - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission denied. Only admins can create group provider settings'; - END IF; - - IF input_field !~* 'group|provider|id|hostname|username|password|privilege' THEN - RAISE EXCEPTION 'Invalid field specified (%)',input_field; - END IF; - - EXECUTE 'UPDATE "management"."group_settings" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "group" = $1' - USING input_old_group, input_field, input_new_value; - - PERFORM api.syslog('modify_group_settings:"'||input_old_group||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'group' THEN - RETURN QUERY (SELECT * FROM "management"."group_settings" WHERE "group" = input_new_value); - ELSE - RETURN QUERY (SELECT * FROM "management"."group_settings" WHERE "group" = input_old_group); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_group_settings(input_old_group text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_group_settings(input_old_group text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_group_settings(input_old_group text, input_field text, input_new_value text) IS 'Modify group authentication and provider settings'; - - --- --- Name: modify_interface(macaddr, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_interface(input_old_mac macaddr, input_field text, input_new_value text) RETURNS SETOF systems.interfaces - LANGUAGE plpgsql - AS $_$ - BEGIN - - -- Check privileges - IF (SELECT "write" FROM api.get_system_permissions((SELECT "system_name" FROM "systems"."interfaces" WHERE "mac" = input_old_mac))) IS FALSE THEN - RAISE EXCEPTION 'Permission denied'; - END IF; - - -- Check allowed fields - IF input_field !~* 'mac|comment|system_name|name' THEN - RAISE EXCEPTION 'Invalid field % specified',input_field; - END IF; - - -- Update record - - IF input_field ~* 'mac' THEN - EXECUTE 'UPDATE "systems"."interfaces" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "mac" = $1' - H - USING input_old_mac, input_field, macaddr(input_new_value); - ELSE - EXECUTE 'UPDATE "systems"."interfaces" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "mac" = $1' - USING input_old_mac, input_field, input_new_value; - END IF; - - -- Done - PERFORM api.syslog('modify_interface:"'||input_old_mac||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'mac' THEN - RETURN QUERY (SELECT * FROM "systems"."interfaces" WHERE "mac" = macaddr(input_new_value)); - ELSE - RETURN QUERY (SELECT * FROM "systems"."interfaces" WHERE "mac" = input_old_mac); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_interface(input_old_mac macaddr, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_interface(input_old_mac macaddr, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_interface(input_old_mac macaddr, input_field text, input_new_value text) IS 'Modify an existing system interface'; - - --- --- Name: modify_interface_address(inet, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_interface_address(input_old_address inet, input_field text, input_new_value text) RETURNS SETOF systems.interface_addresses - LANGUAGE plpgsql - AS $_$ - DECLARE - isprim BOOLEAN; - primcount INTEGER; - BEGIN - - -- Check privilegesinput_old_name - IF (SELECT "write" FROM api.get_system_permissions(api.get_interface_address_system(input_old_address))) IS FALSE THEN - RAISE EXCEPTION 'Permission denied'; - END IF; - - -- Check allowed fields - IF input_field !~* 'comment|address|config|isprimary|mac|class|renew_date' THEN - RAISE EXCEPTION 'Invalid field % specified',input_field; - END IF; - - -- Check dynamic - IF api.ip_is_dynamic(input_old_address) IS TRUE THEN - IF input_field ~* 'config|class' THEN - RAISE EXCEPTION 'Cannot modify the configuration or class of a dynamic address'; - END IF; - END IF; - - -- Check for primary - SELECT "isprimary" INTO isprim FROM "systems"."interface_addresses" WHERE "address" = input_old_address; - - IF input_field ~* 'mac' THEN - SELECT COUNT(*) INTO primcount FROM "systems"."interface_addresses" WHERE "mac" = input_new_value::macaddr AND "isprimary" IS TRUE; - IF primcount = 0 THEN - isprim := TRUE; - ELSE - isprim := FALSE; - END IF; - END IF; - - IF input_field ~* 'address' THEN - IF (SELECT "use" FROM "api"."get_ip_ranges"() WHERE "name" = (SELECT "api"."get_address_range"(input_new_value::inet))) ~* 'ROAM' THEN - RAISE EXCEPTION 'Specified new address (%) is contained within a Dynamic range',input_new_value; - END IF; - END IF; - - IF input_field ~* 'renew_date' AND input_new_value IS NULL THEN - input_new_value := api.get_default_renew_date(api.get_interface_address_system(input_old_address)); - END IF; - - -- Update record - - IF input_field ~* 'mac' THEN - EXECUTE 'UPDATE "systems"."interface_addresses" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user(), isprimary = $4 - WHERE "address" = $1' - USING input_old_address, input_field, macaddr(input_new_value),isprim; - ELSIF input_field ~* 'address' THEN - EXECUTE 'UPDATE "systems"."interface_addresses" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "address" = $1' - USING input_old_address, input_field, inet(input_new_value); - ELSIF input_field ~* 'isprimary' THEN - EXECUTE 'UPDATE "systems"."interface_addresses" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "address" = $1' - USING input_old_address, input_field, bool(input_new_value); - ELSIF input_field ~* 'renew_date' THEN - EXECUTE 'UPDATE "systems"."interface_addresses" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "address" = $1' - USING input_old_address, input_field, input_new_value::date; - ELSEIF input_field ~* 'config' THEN - EXECUTE 'UPDATE "systems"."interface_addresses" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "address" = $1' - USING input_old_address, input_field, input_new_value; - -- Need to force DNS records to be created - IF input_new_value ~* 'static' THEN - UPDATE "dns"."a" SET "address" = input_old_address WHERE "address" = input_old_address; - END IF; - ELSE - EXECUTE 'UPDATE "systems"."interface_addresses" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "address" = $1' - USING input_old_address, input_field, input_new_value; - END IF; - - -- Done - PERFORM api.syslog('modify_interface_address:"'||input_old_address||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'address' THEN - RETURN QUERY (SELECT * FROM "systems"."interface_addresses" WHERE "address" = inet(input_new_value)); - ELSE - RETURN QUERY (SELECT * FROM "systems"."interface_addresses" WHERE "address" = input_old_address); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_interface_address(input_old_address inet, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_interface_address(input_old_address inet, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_interface_address(input_old_address inet, input_field text, input_new_value text) IS 'Modify an existing interface address'; - - --- --- Name: modify_ip_range(text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_ip_range(input_old_name text, input_field text, input_new_value text) RETURNS SETOF ip.ranges - LANGUAGE plpgsql - AS $_$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - RAISE EXCEPTION 'Permission to modify range (%). Not admin.',input_old_name; - END IF; - - -- Check allowed fields - IF input_field !~* 'first_ip|last_ip|comment|use|name|subnet|class|zone' THEN - RAISE EXCEPTION 'Invalid field specified (%)',input_field; - END IF; - - -- Update record - IF input_field ~* 'first_ip|last_ip' THEN - EXECUTE 'UPDATE "ip"."ranges" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "name" = $1' - USING input_old_name, input_field, inet(input_new_value); - ELSIF input_field ~* 'subnet' THEN - EXECUTE 'UPDATE "ip"."ranges" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "name" = $1' - USING input_old_name, input_field, cidr(input_new_value); - ELSE - EXECUTE 'UPDATE "ip"."ranges" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "name" = $1' - USING input_old_name, input_field, input_new_value; - END IF; - - -- Done - PERFORM api.syslog('modify_ip_range:"'||input_old_name||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'name' THEN - RETURN QUERY (SELECT * FROM "ip"."ranges" WHERE "name" = input_new_value); - ELSE - RETURN QUERY (SELECT * FROM "ip"."ranges" WHERE "name" = input_old_name); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_ip_range(input_old_name text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_ip_range(input_old_name text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_ip_range(input_old_name text, input_field text, input_new_value text) IS 'Modify an IP range'; - - --- --- Name: modify_ip_subnet(cidr, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_ip_subnet(input_old_subnet cidr, input_field text, input_new_value text) RETURNS SETOF ip.subnets - LANGUAGE plpgsql - AS $_$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "ip"."subnets" WHERE "subnet" = input_old_subnet) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission to edit subnet % denied. You are not owner',input_old_subnet; - END IF; - - IF input_field ~* 'owner' AND input_new_value != api.get_current_user() THEN - RAISE EXCEPTION 'Only administrators can define a different owner (%).',input_new_value; - END IF; - END IF; - - -- Check allowed fields - IF input_field !~* 'subnet|comment|autogen|name|owner|zone|dhcp_enable|datacenter|vlan' THEN - RAISE EXCEPTION 'Invalid field specified (%)',input_field; - END IF; - - -- Update record - IF input_field ~* 'dhcp_enable|autogen' THEN - EXECUTE 'UPDATE "ip"."subnets" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "subnet" = $1' - USING input_old_subnet, input_field, bool(input_new_value); - ELSIF input_field ~* 'subnet' THEN - EXECUTE 'UPDATE "ip"."subnets" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "subnet" = $1' - USING input_old_subnet, input_field, cidr(input_new_value); - ELSIF input_field ~* 'vlan' THEN - EXECUTE 'UPDATE "ip"."subnets" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "subnet" = $1' - USING input_old_subnet, input_field, input_new_value::integer; - ELSE - EXECUTE 'UPDATE "ip"."subnets" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "subnet" = $1' - USING input_old_subnet, input_field, input_new_value; - END IF; - - -- Done - PERFORM api.syslog('modify_ip_subnet:"'||input_old_subnet||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'subnet' THEN - RETURN QUERY (SELECT * FROM "ip"."subnets" WHERE "subnet" = cidr(input_new_value)); - ELSE - RETURN QUERY (SELECT * FROM "ip"."subnets" WHERE "subnet" = input_old_subnet); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_ip_subnet(input_old_subnet cidr, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_ip_subnet(input_old_subnet cidr, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_ip_subnet(input_old_subnet cidr, input_field text, input_new_value text) IS 'Modify an IP subnet'; - - --- --- Name: modify_network_snmp(text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_network_snmp(input_old_system text, input_field text, input_new_value text) RETURNS void - LANGUAGE plpgsql - AS $_$ - BEGIN - - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF (SELECT "owner" FROM "systems"."systems" WHERE "system_name" = input_old_system) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied: you are not owner'; - END IF; - END IF; - - -- Check fields - IF input_field !~* 'ro_community|rw_community|system_name|address' THEN - RAISE EXCEPTION 'Invalid field % specified',input_field; - END IF; - - IF input_field ~* 'address' THEN - IF(api.get_interface_address_system(input_new_value::inet) != input_old_system) THEN - RAISE EXCEPTION 'Address % is not a part of the system %',input_new_value,input_old_system; - END IF; - - IF input_new_value::inet << api.get_site_configuration('DYNAMIC_SUBNET')::cidr THEN - RAISE EXCEPTION 'System address cannot be dynamic'; - END IF; - END IF; - - -- Mod it - IF input_field ~* 'address' THEN - EXECUTE 'UPDATE "network"."snmp" SET ' || quote_ident($2) || ' = $3 - WHERE "system_name" = $1' - USING input_old_system, input_field, input_new_value::inet; - ELSE - EXECUTE 'UPDATE "network"."snmp" SET ' || quote_ident($2) || ' = $3 - WHERE "system_name" = $1' - USING input_old_system, input_field, input_new_value; - END IF; - - -- Done - PERFORM api.syslog('modify_network_snmp:"'||input_old_system||'","'||input_field||'","'||input_new_value||'"'); - END; -$_$; - - -ALTER FUNCTION api.modify_network_snmp(input_old_system text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_network_snmp(input_old_system text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_network_snmp(input_old_system text, input_field text, input_new_value text) IS 'Modify credentials for a system'; - - --- --- Name: modify_network_switchport_admin_state(inet, text, text, boolean); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION modify_network_switchport_admin_state(input_address inet, input_port text, input_rw_community text, input_state boolean) RETURNS void - LANGUAGE plperlu - AS $_$ - use strict; - use warnings; - use Net::SNMP; - no warnings('redefine'); - - # Local variables and things - our $host = shift; - our $portName = shift; - our $community = shift; - our $state = shift; - - # OID List - our $ifNameList_OID = '.1.3.6.1.2.1.31.1.1.1.1'; - #our $ifAliasList_OID = '1.3.6.1.2.1.31.1.1.1.18'; - - # Stored data - our %ifIndexData; - our $ifAdminStatusOid = '.1.3.6.1.2.1.2.2.1.7'; - - # Establish session - our ($session,$error) = Net::SNMP->session ( - -hostname => $host, - -community => $community, - ); - - # Get the index of all interfaces - my $ifNameList = $session->get_table(-baseoid => $ifNameList_OID); - while (my($ifIndex,$ifName) = each(%$ifNameList)) { - $ifIndex =~ s/$ifNameList_OID\.//; - if($ifIndex =~ m/\d{5}/) { - # $ifIndexData{$ifIndex} = $ifName; - if($ifName eq $portName) { - $ifAdminStatusOid .= ".$ifIndex"; - } - } - # warn("$ifIndex - $ifName\n"); - } - - # Finalize the data - my $snmpState = 1; - if($state eq 'f') { - $snmpState = 2; - } - - # Set the new description - my $result = $session->set_request( - -varbindlist => [ $ifAdminStatusOid, INTEGER, $snmpState ], - ); - #die($state); - #die($ifAdminStatusOid); - - if(!$result) { - die("Error: ",$session->error()); - } - - # Close initial session - $session->close(); -$_$; - - -ALTER FUNCTION api.modify_network_switchport_admin_state(input_address inet, input_port text, input_rw_community text, input_state boolean) OWNER TO postgres; - --- --- Name: FUNCTION modify_network_switchport_admin_state(input_address inet, input_port text, input_rw_community text, input_state boolean); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION modify_network_switchport_admin_state(input_address inet, input_port text, input_rw_community text, input_state boolean) IS 'Modify the admin state of a network switchport'; - - --- --- Name: modify_network_switchport_description(inet, text, text, text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION modify_network_switchport_description(input_address inet, input_port text, input_rw_community text, input_description text) RETURNS void - LANGUAGE plperlu - AS $_$ - use strict; - use warnings; - use Net::SNMP; - no warnings('redefine'); - - # Local variables and things - our $host = shift; - our $portName = shift; - our $community = shift; - our $description = shift; - - # OID List - our $ifNameList_OID = '.1.3.6.1.2.1.31.1.1.1.1'; - our $ifAliasList_OID = '1.3.6.1.2.1.31.1.1.1.18'; - - # Stored data - our %ifIndexData; - our $ifAliasOid = '1.3.6.1.2.1.31.1.1.1.18'; - - # Establish session - our ($session,$error) = Net::SNMP->session ( - -hostname => $host, - -community => $community, - ); - - # Get the index of all interfaces - my $ifNameList = $session->get_table(-baseoid => $ifNameList_OID); - while (my($ifIndex,$ifName) = each(%$ifNameList)) { - $ifIndex =~ s/$ifNameList_OID\.//; - if($ifIndex =~ m/\d{5}/) { - # $ifIndexData{$ifIndex} = $ifName; - if($ifName eq $portName) { - $ifAliasOid .= ".$ifIndex"; - } - } - # warn("$ifIndex - $ifName\n"); - } - - # Set the new description - my $result = $session->set_request( - -varbindlist => [ $ifAliasOid, OCTET_STRING, $description ], - ); - - if(!$result) { - die("Error: ",$session->error()); - } - - # Close initial session - $session->close(); -$_$; - - -ALTER FUNCTION api.modify_network_switchport_description(input_address inet, input_port text, input_rw_community text, input_description text) OWNER TO postgres; - --- --- Name: FUNCTION modify_network_switchport_description(input_address inet, input_port text, input_rw_community text, input_description text); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION modify_network_switchport_description(input_address inet, input_port text, input_rw_community text, input_description text) IS 'Modify the description of a network switchport'; - - --- --- Name: modify_platform(text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_platform(input_old_name text, input_field text, input_new_value text) RETURNS SETOF systems.platforms - LANGUAGE plpgsql - AS $_$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - RAISE EXCEPTION 'Permission to edit platform denied. You are not admin'; - END IF; - - -- Check allowed fields - IF input_field !~* 'platform_name|architecture|disk|cpu|memory' THEN - RAISE EXCEPTION 'Invalid field % specified',input_field; - END IF; - - IF input_field ~* 'memory' THEN - EXECUTE 'UPDATE "systems"."platforms" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "platform_name" = $1' - USING input_old_name, input_field, input_new_value::integer; - ELSE - EXECUTE 'UPDATE "systems"."platforms" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "platform_name" = $1' - USING input_old_name, input_field, input_new_value; - END IF; - - PERFORM api.syslog('modify_platform:"'||input_old_name||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'platform_name' THEN - RETURN QUERY (SELECT * FROM "systems"."platforms" WHERE "platform_name" = input_new_value); - ELSE - RETURN QUERY (SELECT * FROM "systems"."platforms" WHERE "platform_name" = input_old_name); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_platform(input_old_name text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_platform(input_old_name text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_platform(input_old_name text, input_field text, input_new_value text) IS 'Modify a hardware platform'; - - --- --- Name: modify_site_configuration(text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_site_configuration(input_directive text, input_value text) RETURNS SETOF management.configuration - LANGUAGE plpgsql - AS $$ - BEGIN - - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission denied. Only admins can modify site directives'; - END IF; - - -- Create directive - UPDATE "management"."configuration" SET "value" = input_value WHERE "option" = input_directive; - - -- Done - PERFORM api.syslog('modify_site_configuration:"'||input_directive||'","'||input_value||'"'); - RETURN QUERY (SELECT * FROM "management"."configuration" WHERE "option" = input_directive AND "value" = input_value); - END; -$$; - - -ALTER FUNCTION api.modify_site_configuration(input_directive text, input_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_site_configuration(input_directive text, input_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_site_configuration(input_directive text, input_value text) IS 'Modify a site configuration directive'; - - --- --- Name: modify_system(text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_system(input_old_name text, input_field text, input_new_value text) RETURNS SETOF systems.systems - LANGUAGE plpgsql - AS $_$ - BEGIN - -- Check privileges - IF (SELECT "write" FROM api.get_system_permissions(input_old_name)) IS FALSE THEN - RAISE EXCEPTION 'Permission denied'; - END IF; - - -- Check allowed fields - IF input_field !~* 'system_name|owner|comment|type|os_name|platform_name|asset|group|datacenter|location' THEN - RAISE EXCEPTION 'Invalid field % specified',input_field; - END IF; - - -- Update record - - EXECUTE 'UPDATE "systems"."systems" SET ' || quote_ident($2) || ' = $3, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "system_name" = $1' - USING input_old_name, input_field, input_new_value; - - -- Done - PERFORM api.syslog('modify_system:"'||input_old_name||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'system_name' THEN - RETURN QUERY (SELECT * FROM "systems"."systems" WHERE "system_name" = input_new_value); - ELSE - RETURN QUERY (SELECT * FROM "systems"."systems" WHERE "system_name" = input_old_name); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_system(input_old_name text, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_system(input_old_name text, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_system(input_old_name text, input_field text, input_new_value text) IS 'Modify an existing system'; - - --- --- Name: modify_vlan(text, integer, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION modify_vlan(input_old_datacenter text, input_old_vlan integer, input_field text, input_new_value text) RETURNS SETOF network.vlans - LANGUAGE plpgsql - AS $_$ - BEGIN - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Only admins can create VLANs'; - END IF; - - IF input_field !~* 'datacenter|vlan|name|comment' THEN - RAISE EXCEPTION 'Invalid field %',input_field; - END IF; - - IF input_field ~* 'vlan' THEN - EXECUTE 'UPDATE "network"."vlans" SET ' || quote_ident($3) || ' = $4, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "datacenter" = $1 AND "vlan" = $2' - USING input_old_datacenter, input_old_vlan, input_field, input_new_value::integer; - ELSE - EXECUTE 'UPDATE "network"."vlans" SET ' || quote_ident($3) || ' = $4, - date_modified = localtimestamp(0), last_modifier = api.get_current_user() - WHERE "datacenter" = $1 AND "vlan" = $2' - USING input_old_datacenter, input_old_vlan, input_field, input_new_value; - END IF; - - PERFORM api.syslog('modify_vlan:"'||input_old_datacenter||'","'||input_old_vlan||'","'||input_field||'","'||input_new_value||'"'); - IF input_field ~* 'datacenter' THEN - RETURN QUERY (SELECT * FROM "network"."vlans" WHERE "datacenter" = input_new_value AND "vlan" = input_old_vlan); - ELSEIF input_field ~* 'vlan' THEN - RETURN QUERY (SELECT * FROM "network"."vlans" WHERE "datacenter" = input_old_datacenter AND "vlan" = input_new_value::integer); - ELSE - RETURN QUERY (SELECT * FROM "network"."vlans" WHERE "datacenter" = input_old_datacenter AND "vlan" = input_old_vlan); - END IF; - END; -$_$; - - -ALTER FUNCTION api.modify_vlan(input_old_datacenter text, input_old_vlan integer, input_field text, input_new_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION modify_vlan(input_old_datacenter text, input_old_vlan integer, input_field text, input_new_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION modify_vlan(input_old_datacenter text, input_old_vlan integer, input_field text, input_new_value text) IS 'Modify a VLAN'; - - --- --- Name: notify_expiring_addresses(); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION notify_expiring_addresses() RETURNS void - LANGUAGE plpgsql - AS $$ - DECLARE - SystemData RECORD; - BEGIN - FOR SystemData IN (SELECT api.get_interface_address_owner("address") AS "owner","address","renew_date" FROM "systems"."interface_addresses" WHERE "renew_date" <= current_date + api.get_site_configuration('EMAIL_NOTIFICATION_INTERVAL')::interval) LOOP - PERFORM "api"."send_renewal_email"(api.get_user_email(SystemData.owner), SystemData.address, api.get_interface_address_system(SystemData.address), (SELECT "api"."get_site_configuration"('EMAIL_DOMAIN')), (SELECT api.get_site_configuration('WEB_URL')),(SELECT api.get_site_configuration('MAIL_HOST'))); - PERFORM api.syslog('notified '||api.get_user_email(SystemData.owner)||' of expiring address: '||SystemData.address); - END LOOP; - END; -$$; - - -ALTER FUNCTION api.notify_expiring_addresses() OWNER TO starrs_admin; - --- --- Name: FUNCTION notify_expiring_addresses(); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION notify_expiring_addresses() IS 'Notify users of soon-to-expire addresses'; - - --- --- Name: nslookup(inet); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION nslookup(input_address inet) RETURNS TABLE(fqdn text) - LANGUAGE plpgsql - AS $$ - BEGIN - RETURN QUERY (SELECT "hostname"||'.'||"zone" FROM "dns"."a" WHERE "address" = input_address); - END; -$$; - - -ALTER FUNCTION api.nslookup(input_address inet) OWNER TO starrs_admin; - --- --- Name: FUNCTION nslookup(input_address inet); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION nslookup(input_address inet) IS 'Get the DNS name of an IP address in the database'; - - --- --- Name: nsupdate(text, text, text, inet, text, text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION nsupdate(zone text, keyname text, key text, server inet, action text, record text) RETURNS text - LANGUAGE plperlu - AS $_$ - use strict; - use warnings; - use v5.10; - use Net::DNS; - no warnings('redefine'); - - # Local variable information - our $zone = shift(@_) or die("Invalid zone argument"); - our $keyname = shift(@_) or die("Invalid keyname argument"); - our $key = shift(@_) or die("Invalid key argument"); - our $server = shift(@_) or die("Invalid server argument"); - our $action = shift(@_) or die("Invalid action argument"); - our $record = shift(@_) or die("Invalid record argument"); - - # DNS Server - our $res = Net::DNS::Resolver->new; - $res->nameservers($server); - - - # Update packet - our $update = Net::DNS::Update->new($zone); - - # Do something - my $returnCode; - if($action eq "DELETE") { - $returnCode = &delete(); - } - elsif($action eq "ADD") { - $returnCode = &add(); - } - else { - $returnCode = "INVALID ACTION"; - } - - # Delete a record - sub delete() { - # The record must be there to delete it - # $update->push(pre => yxrrset($record)); - - # Delete the record - $update->push(update => rr_del($record)); - - # Sign it - $update->sign_tsig($keyname, $key); - - # Send it - &send(); - } - - # Add a record - sub add() { - # MX and TXT records will already exist. Otherwise the record you are - # creating should not already be in the zone. That would be silly. - # - # Frak it, you better be sure IMPULSE owns your DNS zone. Otherwise old records - # WILL be overwriten. - # - # if($record !~ m/\s(MX|TXT|NS)\s/) { - # $update->push(pre => nxrrset($record)); - # } - - # Add the record - $update->push(update => rr_add($record)); - - # Sign it - $update->sign_tsig($keyname, $key); - - # Send it - &send(); - } - - # Send an update - sub send() { - my $reply = $res->send($update); - if($reply) { - if($reply->header->rcode eq 'NOERROR') { - return 0; - } - else { - return &interpret_error($reply->header->rcode); - } - } - else { - return &interpret_error($res->errorstring); - } - } - - # Interpret the error codes if any - sub interpret_error() { - my $error = shift(@_); - - given ($error) { - when (/NXRRSET/) { return "Error $error: Name does not exist"; } - when (/YXRRSET/) { return "Error $error: Name exists"; } - when (/NOTAUTH/) { return "Error $error: Not authorized. Check system clocks and or key"; } - default { return "$error unrecognized"; } - } - } - - return $returnCode; -$_$; - - -ALTER FUNCTION api.nsupdate(zone text, keyname text, key text, server inet, action text, record text) OWNER TO postgres; - --- --- Name: ping(inet); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION ping(inet) RETURNS boolean - LANGUAGE plperlu - AS $_X$ - #! /usr/bin/perl - use strict; - use warnings; - use Net::IP qw(ip_get_version); - - my $res = 1; - - if (ip_get_version($_[0]) == 6) { - $res = system("ping6 -W 1 -c 1 $_[0] > /dev/null"); - } else { - $res = system("ping -W 1 -c 1 $_[0] > /dev/null"); - } - - if($res == 0) { - return 1; - } else { - return 0; - } -$_X$; - - -ALTER FUNCTION api.ping(inet) OWNER TO postgres; - --- --- Name: FUNCTION ping(inet); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION ping(inet) IS 'See if a host is up on the network'; - - --- --- Name: query_address_reverse(inet); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION query_address_reverse(inet) RETURNS text - LANGUAGE plperlu - AS $_$ - use strict; - use warnings; - use Net::DNS; - use Net::IP; - use Net::IP qw(:PROC); - use v5.10; - - # Define some variables - my $address = shift(@_) or die "Unable to get address"; - - # Generate the reverse string (d.c.b.a.in-addr.arpa.) - my $reverse = new Net::IP ($address)->reverse_ip() or die (Net::IP::Error()); - - # Create the resolver - my $res = Net::DNS::Resolver->new; - - # Run the query - my $rr = $res->query($reverse,'PTR'); - - # Check for a response - if(!defined($rr)) { - return; - } - - # Parse the response - my @answer = $rr->answer; - foreach my $response(@answer) { - return $response->ptrdname; - } -$_$; - - -ALTER FUNCTION api.query_address_reverse(inet) OWNER TO postgres; - --- --- Name: FUNCTION query_address_reverse(inet); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION query_address_reverse(inet) IS 'Print the forward host of a reverse lookup'; - - --- --- Name: query_axfr(text, text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION query_axfr(text, text) RETURNS SETOF dns.zone_audit_data - LANGUAGE plperlu - AS $_X$ - use strict; - use warnings; - use Net::DNS; - use v5.10; - use Data::Dumper; - - my $zone = shift(@_) or die "Unable to get zone"; - my $nameserver = shift(@_) or die "Unable to get nameserver for zone"; - - my $res = Net::DNS::Resolver->new; - $res->nameservers($nameserver); - - my @answer = $res->axfr($zone); - - foreach my $result (@answer) { - &print_data($result); - } - - sub print_data() { - my $rr = $_[0]; - given($rr->type) { - when (/^A|AAAA$/) { - return_next({host=>$rr->name, ttl=>$rr->ttl, type=>$rr->type, address=>$rr->address}); - } - when (/^CNAME$/) { - return_next({host=>$rr->name,ttl=>$rr->ttl,type=>$rr->type,target=>$rr->cname}); - } - when (/^SRV$/) { - return_next({host=>$rr->name,ttl=>$rr->ttl,type=>$rr->type,priority=>$rr->priority,weight=>$rr->weight,port=>$rr->port,target=>$rr->target}); - } - when (/^NS$/) { - return_next({host=>$rr->nsdname, ttl=>$rr->ttl, type=>$rr->type}); - } - when (/^MX$/) { - return_next({host=>$rr->exchange, ttl=>$rr->ttl, type=>$rr->type, preference=>$rr->preference}); - } - when (/^TXT$/) { - return_next({host=>$rr->name, ttl=>$rr->ttl, type=>$rr->type, text=>$rr->char_str_list}); - } - when (/^SOA$/) { - return_next({host=>$rr->name, target=>$rr->mname, ttl=>$rr->ttl, contact=>$rr->rname, serial=>$rr->serial, refresh=>$rr->refresh, retry=>$rr->retry, expire=>$rr->expire, minimum=>$rr->minimum, type=>$rr->type}); - } - when (/^PTR$/) { - return_next({host=>$rr->name, target=>$rr->ptrdname, ttl=>$rr->ttl, type=>$rr->type}); - } - } - } - return undef; -$_X$; - - -ALTER FUNCTION api.query_axfr(text, text) OWNER TO postgres; - --- --- Name: FUNCTION query_axfr(text, text); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION query_axfr(text, text) IS 'Query a nameserver for the DNS zone transfer to use for auditing'; - - --- --- Name: query_dns_soa(text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION query_dns_soa(text) RETURNS SETOF dns.soa - LANGUAGE plperlu - AS $_$ - use strict; - use warnings; - use Net::DNS; - - # Get the zone - my $zone = shift(@_) or die "Unable to get DNS zone to query"; - - # Date - my $date = spi_exec_query("SELECT localtimestamp(0)"); - $date = $date->{rows}[0]->{timestamp}; - my $user = spi_exec_query("SELECT api.get_current_user()"); - $user = $user->{rows}[0]->{get_current_user}; - - # Establish the resolver and make the query - my $res = Net::DNS::Resolver->new; - my $rr = $res->query($zone,'soa'); - - # Check if it actually returned - if(!defined($rr)) { - die "Unable to find record for zone $zone"; - } - - # Spit out the serial - my @answer = $rr->answer; - return_next({zone=>$zone, nameserver=>$answer[0]->mname, ttl=>$answer[0]->ttl, contact=>$answer[0]->rname, serial=>$answer[0]->serial, refresh=>$answer[0]->refresh, retry=>$answer[0]->retry, expire=>$answer[0]->expire, minimum=>$answer[0]->minimum, date_created=>$date, date_modified=>$date, last_modifier=>$user}); - return undef; -$_$; - - -ALTER FUNCTION api.query_dns_soa(text) OWNER TO postgres; - --- --- Name: FUNCTION query_dns_soa(text); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION query_dns_soa(text) IS 'Use the hosts resolver to query and create an SOA'; - - --- --- Name: query_zone_serial(text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION query_zone_serial(text) RETURNS text - LANGUAGE plperlu - AS $_$ - use strict; - use warnings; - use Net::DNS; - - # Get the zone - my $zone = shift(@_) or die "Unable to get DNS zone to query"; - - # Establish the resolver and make the query - my $res = Net::DNS::Resolver->new; - my $rr = $res->query($zone,'soa'); - - # Check if it actually returned - if(!defined($rr)) { - die "Unable to find record for zone $zone"; - } - - # Spit out the serial - my @answer = $rr->answer; - return $answer[0]->serial; -$_$; - - -ALTER FUNCTION api.query_zone_serial(text) OWNER TO postgres; - --- --- Name: FUNCTION query_zone_serial(text); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION query_zone_serial(text) IS 'Query this hosts resolver for the serial number of the zone.'; - - --- --- Name: reload_cam(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION reload_cam(input_system_name text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF api.get_current_user() != (SELECT "owner" FROM "systems"."systems" WHERE "system_name" = input_system_name) THEN - RAISE EXCEPTION 'Permission denied: Not owner'; - END IF; - END IF; - - INSERT INTO "network"."cam_cache" ("system_name","mac","vlan","date_created","date_modified","last_modifier","ifindex") ( - SELECT input_system_name,mac,vlan,localtimestamp(0),localtimestamp(0),api.get_current_user(),ifindex - FROM api.get_switchview_device_cam(input_system_name) - ); - DELETE FROM "network"."cam_cache" WHERE "system_name" = input_system_name AND "date_created" != localtimestamp(0); - END; -$$; - - -ALTER FUNCTION api.reload_cam(input_system_name text) OWNER TO starrs_admin; - --- --- Name: FUNCTION reload_cam(input_system_name text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION reload_cam(input_system_name text) IS 'Reload the cam cache for a system'; - - --- --- Name: reload_group_members(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION reload_group_members(input_group text) RETURNS SETOF management.group_members - LANGUAGE plpgsql - AS $$ - DECLARE - MemberData RECORD; - ReloadData RECORD; - Settings RECORD; - BEGIN - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission denied. Only admins can reload group members'; - END IF; - - SELECT * INTO Settings FROM api.get_group_settings(input_group); - - IF Settings."provider" !~* 'ldap|vcloud|ad' THEN - RAISE EXCEPTION 'Cannot reload local group'; - END IF; - - IF Settings."provider" IS NULL THEN - RAISE EXCEPTION 'Cannot reload group with no provider: %',input_group; - END IF; - - FOR MemberData IN (SELECT * FROM api.get_group_members(input_group)) LOOP - PERFORM api.remove_group_member(input_group, MemberData."user"); - END LOOP; - - IF Settings."provider" ~* 'LDAP' THEN - FOR ReloadData IN (SELECT * FROM api.get_ldap_group_members(Settings."hostname", Settings."id", Settings."username", Settings."password")) LOOP - PERFORM api.create_group_member(input_group, ReloadData.get_ldap_group_members, Settings."privilege"); - END LOOP; - END IF; - - IF Settings."provider" ~* 'vcloud' THEN - FOR ReloadData IN (SELECT * FROM api.get_vcloud_group_members(Settings."hostname", Settings."id", Settings."username", Settings."password")) LOOP - PERFORM api.create_group_member(input_group, ReloadData.get_vcloud_group_members, Settings."privilege"); - END LOOP; - END IF; - - PERFORM api.syslog('reload_group_members:"'||input_group||'"'); - RETURN QUERY (SELECT * FROM api.get_group_members(input_group)); - - END; -$$; - - -ALTER FUNCTION api.reload_group_members(input_group text) OWNER TO starrs_admin; - --- --- Name: remove_availability_zone(text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_availability_zone(input_datacenter text, input_zone text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission denied: Only admins can remove availability_zones'; - END IF; - - -- Perform delete - DELETE FROM "systems"."availability_zones" WHERE "datacenter" = input_datacenter AND "zone" = input_zone; - - -- Done - PERFORM api.syslog('remove_availability_zone:"'||input_datacenter||'","'||input_zone||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_availability_zone(input_datacenter text, input_zone text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_availability_zone(input_datacenter text, input_zone text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_availability_zone(input_datacenter text, input_zone text) IS 'Remove an availability zone'; - - --- --- Name: remove_datacenter(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_datacenter(input_name text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission denied: Only admins can remove datacenters'; - END IF; - - -- Perform delete - DELETE FROM "systems"."datacenters" WHERE "datacenter" = input_name; - - -- Done - PERFORM api.syslog('remove_datacenter:"'||input_name||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_datacenter(input_name text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_datacenter(input_name text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_datacenter(input_name text) IS 'remove a datacenter'; - - --- --- Name: remove_dhcp_class(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_dhcp_class(input_class text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - RAISE EXCEPTION 'Permission to remove dhcp class denied for %. Not admin.',api.get_current_user(); - END IF; - - -- Remove class - DELETE FROM "dhcp"."classes" WHERE "class" = input_class; - - -- Done - PERFORM api.syslog('remove_dhcp_class:"'||input_class||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_dhcp_class(input_class text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_dhcp_class(input_class text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_dhcp_class(input_class text) IS 'Delete an existing DHCP class'; - - --- --- Name: remove_dhcp_class_option(text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_dhcp_class_option(input_class text, input_option text, input_value text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - RAISE EXCEPTION 'Permission to remove dhcp class option denied for %. Not admin.',api.get_current_user(); - END IF; - - -- Remove class option - DELETE FROM "dhcp"."class_options" - WHERE "class" = input_class AND "option" = input_option AND "value" = input_value; - - -- Done - PERFORM api.syslog('remove_dhcp_class_option:"'||input_class||'","'||input_option||'","'||input_value||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_dhcp_class_option(input_class text, input_option text, input_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_dhcp_class_option(input_class text, input_option text, input_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_dhcp_class_option(input_class text, input_option text, input_value text) IS 'Delete an existing DHCP class option'; - - --- --- Name: remove_dhcp_global_option(text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_dhcp_global_option(input_option text, input_value text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - RAISE EXCEPTION 'Permission to remove dhcp global option denied for %. Not admin.',api.get_current_user(); - END IF; - - -- Delete global option - DELETE FROM "dhcp"."global_options" - WHERE "option" = input_option AND "value" = input_value; - - -- Done - PERFORM api.syslog('remove_dhcp_global_option:"'||input_option||'","'||input_value||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_dhcp_global_option(input_option text, input_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_dhcp_global_option(input_option text, input_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_dhcp_global_option(input_option text, input_value text) IS 'Delete an existing DHCP global option'; - - --- --- Name: remove_dhcp_range_option(text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_dhcp_range_option(input_range text, input_option text, input_value text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - RAISE EXCEPTION 'Permission to remove dhcp range option denied for %. Not admin.',api.get_current_user(); - END IF; - - -- Remove range option - DELETE FROM "dhcp"."range_options" - WHERE "name" = input_range AND "option" = input_option; - - -- Done - PERFORM api.syslog('remove_dhcp_range_option:"'||input_range||'","'||input_option||'","'||input_value||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_dhcp_range_option(input_range text, input_option text, input_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_dhcp_range_option(input_range text, input_option text, input_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_dhcp_range_option(input_range text, input_option text, input_value text) IS 'Delete an existing DHCP range option'; - - --- --- Name: remove_dhcp_subnet_option(cidr, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_dhcp_subnet_option(input_subnet cidr, input_option text, input_value text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - RAISE EXCEPTION 'Permission to remove dhcp subnet option denied for %. Not admin.',api.get_current_user(); - END IF; - - -- Delete subnet option - DELETE FROM "dhcp"."subnet_options" - WHERE "subnet" = input_subnet AND "option" = input_option AND "value" = input_value; - - -- Done - PERFORM api.syslog('remove_dhcp_subnet_option:"'||input_subnet||'","'||input_option||'","'||input_value||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_dhcp_subnet_option(input_subnet cidr, input_option text, input_value text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_dhcp_subnet_option(input_subnet cidr, input_option text, input_value text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_dhcp_subnet_option(input_subnet cidr, input_option text, input_value text) IS 'Delete an existing DHCP subnet option'; - - --- --- Name: remove_dns_address(inet, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_dns_address(input_address inet, input_zone text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "dns"."a" WHERE "address" = input_address AND "zone" = input_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied for % (%) on DNS address %. You are not owner.',api.get_current_user(),api.get_current_user_level(),input_address; - END IF; - END IF; - - -- Remove record - DELETE FROM "dns"."a" WHERE "address" = input_address AND "zone" = input_zone; - - PERFORM api.syslog('remove_dns_address:"'||input_address||'","'||input_zone||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_dns_address(input_address inet, input_zone text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_dns_address(input_address inet, input_zone text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_dns_address(input_address inet, input_zone text) IS 'delete an A or AAAA record'; - - --- --- Name: remove_dns_cname(text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_dns_cname(input_alias text, input_zone text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "dns"."cname" WHERE "alias" = input_alias AND "zone" = input_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied for % (%) on DNS CNAME %. You are not owner.',api.get_current_user(),api.get_current_user_level(),input_alias||'.'||input_zone; - END IF; - END IF; - - -- Remove record - DELETE FROM "dns"."cname" WHERE "alias" = input_alias AND "zone" = input_zone; - - PERFORM api.syslog('remove_dns_cname:"'||input_alias||'","'||input_zone||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_dns_cname(input_alias text, input_zone text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_dns_cname(input_alias text, input_zone text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_dns_cname(input_alias text, input_zone text) IS 'remove a dns cname record for a host'; - - --- --- Name: remove_dns_key(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_dns_key(input_keyname text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "dns"."keys" WHERE "keyname" = input_keyname) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied for % (%) on key %. You are not owner.',api.get_current_user(),api.get_current_user_level(),input_keyname; - END IF; - END IF; - - -- Remove key - DELETE FROM "dns"."keys" WHERE "keyname" = input_keyname; - - PERFORM api.syslog('remove_dns_key:"'||input_keyname||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_dns_key(input_keyname text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_dns_key(input_keyname text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_dns_key(input_keyname text) IS 'Delete existing DNS key'; - - --- --- Name: remove_dns_mailserver(text, integer); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_dns_mailserver(input_zone text, input_preference integer) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "dns"."mx" WHERE "zone" = input_zone AND "preference" = input_preference) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied for % (%) on DNS MX %. You are not owner.',api.get_current_user(),api.get_current_user_level(),input_hostname||'.'||input_zone; - END IF; - END IF; - - -- Remove record - DELETE FROM "dns"."mx" WHERE "zone" = input_zone AND "preference" = input_preference; - - PERFORM api.syslog('remove_dns_mailserver:"'||input_zone||'","'||input_preference||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_dns_mailserver(input_zone text, input_preference integer) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_dns_mailserver(input_zone text, input_preference integer); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_dns_mailserver(input_zone text, input_preference integer) IS 'Delete an existing MX record for a zone'; - - --- --- Name: remove_dns_ns(text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_dns_ns(input_zone text, input_nameserver text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "dns"."zones" WHERE "zone" = input_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied for % (%) on DNS NS %. You are not owner.',api.get_current_user(),api.get_current_user_level(),input_nameserver; - END IF; - END IF; - - -- Remove record - DELETE FROM "dns"."ns" WHERE "zone" = input_zone AND "nameserver" = input_nameserver; - - PERFORM api.syslog('remove_dns_ns:"'||input_zone||'","'||input_nameserver||'"'); - - END; -$$; - - -ALTER FUNCTION api.remove_dns_ns(input_zone text, input_nameserver text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_dns_ns(input_zone text, input_nameserver text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_dns_ns(input_zone text, input_nameserver text) IS 'Remove a DNS NS record from the zone'; - - --- --- Name: remove_dns_soa(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_dns_soa(input_zone text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "dns"."zones" WHERE "zone" = input_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied for % (%) on zone %. You are not owner.',api.get_current_user(),api.get_current_user_level(),input_soa; - END IF; - END IF; - - -- Delete soa - DELETE FROM "dns"."soa" - WHERE "zone" = input_zone; - - PERFORM api.syslog('remove_dns_soa:"'||input_zone||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_dns_soa(input_zone text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_dns_soa(input_zone text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_dns_soa(input_zone text) IS 'Delete existing DNS soa'; - - --- --- Name: remove_dns_srv(text, text, integer, integer, integer); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_dns_srv(input_alias text, input_zone text, input_priority integer, input_weight integer, input_port integer) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "dns"."srv" WHERE "alias" = input_alias AND "zone" = input_zone AND "priority" = input_priority AND "weight" = input_weight AND "port" = input_port) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied for % (%) on DNS SRV %. You are not owner.',api.get_current_user(),api.get_current_user_level(),input_alias||'.'||input_zone; - END IF; - END IF; - - -- Remove record - DELETE FROM "dns"."srv" WHERE "alias" = input_alias AND "zone" = input_zone AND "priority" = input_priority AND "weight" = input_weight AND "port" = input_port; - - PERFORM api.syslog('remove_dns_srv:"'||input_alias||'","'||input_zone||'","'||input_priority||'","'||input_weight||'","'||input_port||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_dns_srv(input_alias text, input_zone text, input_priority integer, input_weight integer, input_port integer) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_dns_srv(input_alias text, input_zone text, input_priority integer, input_weight integer, input_port integer); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_dns_srv(input_alias text, input_zone text, input_priority integer, input_weight integer, input_port integer) IS 'remove a dns srv record'; - - --- --- Name: remove_dns_txt(text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_dns_txt(input_hostname text, input_zone text, input_text text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "dns"."txt" WHERE "hostname" = input_hostname AND "zone" = input_zone AND "text" = input_text) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied for % (%) on DNS TXT %. You are not owner.',api.get_current_user(),api.get_current_user_level(),input_hostname||'.'||input_zone; - END IF; - END IF; - - -- Remove record - DELETE FROM "dns"."txt" WHERE "hostname" = input_hostname AND "zone" = input_zone AND "text" = input_text; - - PERFORM api.syslog('remove_dns_txt:"'||input_hostname||'","'||input_zone||'","'||input_text||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_dns_txt(input_hostname text, input_zone text, input_text text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_dns_txt(input_hostname text, input_zone text, input_text text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_dns_txt(input_hostname text, input_zone text, input_text text) IS 'remove a dns text record for a host'; - - --- --- Name: remove_dns_zone(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_dns_zone(input_zone text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "dns"."zones" WHERE "zone" = input_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied for % (%) on zone %. You are not owner.',api.get_current_user(),api.get_current_user_level(),input_zone; - END IF; - END IF; - - -- Delete zone - DELETE FROM "dns"."zones" - WHERE "zone" = input_zone; - - PERFORM api.syslog('remove_dns_zone:"'||input_zone||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_dns_zone(input_zone text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_dns_zone(input_zone text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_dns_zone(input_zone text) IS 'Delete existing DNS zone'; - - --- --- Name: remove_dns_zone_a(text, inet); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_dns_zone_a(input_zone text, input_address inet) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "dns"."zones" WHERE "zone" = input_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied for % (%) on DNS zone %. You are not owner.',api.get_current_user(),api.get_current_user_level(),input_zone; - END IF; - END IF; - - -- Remove record - DELETE FROM "dns"."zone_a" WHERE "address" = input_address AND "zone" = input_zone; - - PERFORM api.syslog('remove_dns_zone_a:"'||input_zone||'","'||input_address||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_dns_zone_a(input_zone text, input_address inet) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_dns_zone_a(input_zone text, input_address inet); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_dns_zone_a(input_zone text, input_address inet) IS 'delete a zone A or AAAA record'; - - --- --- Name: remove_dns_zone_txt(text, text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_dns_zone_txt(input_hostname text, input_zone text, input_text text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "dns"."zones" WHERE "zone" = input_zone) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied for % (%) on DNS zone_txt %. You are not owner.',api.get_current_user(),api.get_current_user_level(),input_hostname||'.'||input_zone; - END IF; - END IF; - - -- Remove record - IF input_hostname IS NULL THEN - PERFORM api.syslog('remove_dns_zone_txt:"'||input_zone||'","'||input_text||'"'); - DELETE FROM "dns"."zone_txt" WHERE "hostname" IS NULL AND "zone" = input_zone AND "text" = input_text; - ELSE - PERFORM api.syslog('remove_dns_zone_txt:"'||input_hostname||'","'||input_zone||'","'||input_text||'"'); - DELETE FROM "dns"."zone_txt" WHERE "hostname" = input_hostname AND "zone" = input_zone AND "text" = input_text; - END IF; - - END; -$$; - - -ALTER FUNCTION api.remove_dns_zone_txt(input_hostname text, input_zone text, input_text text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_dns_zone_txt(input_hostname text, input_zone text, input_text text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_dns_zone_txt(input_hostname text, input_zone text, input_text text) IS 'remove a dns text record for a host'; - - --- --- Name: remove_group(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_group(input_group text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission denied. Only admins can remove groups.'; - END IF; - - DELETE FROM "management"."groups" WHERE "group" = input_group; - - PERFORM api.syslog('remove_group:"'||input_group||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_group(input_group text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_group(input_group text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_group(input_group text) IS 'Remove a group'; - - --- --- Name: remove_group_member(text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_group_member(input_group text, input_user text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF api.get_current_user() NOT IN (SELECT * FROM api.get_group_admins(input_group)) THEN - RAISE EXCEPTION 'Permission denied. Only admins can remove groups members'; - END IF; - END IF; - - DELETE FROM "management"."group_members" WHERE "group" = input_group AND "user" = input_user; - - PERFORM api.syslog('remove_group_member:"'||input_group||'","'||input_user||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_group_member(input_group text, input_user text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_group_member(input_group text, input_user text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_group_member(input_group text, input_user text) IS 'Remove a group member'; - - --- --- Name: remove_group_settings(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_group_settings(input_group text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission denied. Only admins can remove group provider settings'; - END IF; - - DELETE FROM "management"."group_settings" WHERE "group" = input_group; - - PERFORM api.syslog('remove_group_settings:"'||input_group||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_group_settings(input_group text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_group_settings(input_group text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_group_settings(input_group text) IS 'remove group authentication providers'; - - --- --- Name: remove_interface(macaddr); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_interface(input_mac macaddr) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF (SELECT "owner" FROM "systems"."interfaces" - JOIN "systems"."systems" ON "systems"."systems"."system_name" = "systems"."interfaces"."system_name" - WHERE "systems"."interfaces"."mac" = input_mac) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied on interface %. You are not owner.',input_mac; - END IF; - END IF; - - -- Remove interface - DELETE FROM "systems"."interfaces" WHERE "mac" = input_mac; - - -- Done - PERFORM api.syslog('remove_interface:"'||input_mac||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_interface(input_mac macaddr) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_interface(input_mac macaddr); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_interface(input_mac macaddr) IS 'delete an interface based on MAC address'; - - --- --- Name: remove_interface_address(inet); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_interface_address(input_address inet) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF (SELECT "owner" FROM "systems"."interface_addresses" - JOIN "systems"."interfaces" ON "systems"."interfaces"."mac" = "systems"."interface_addresses"."mac" - JOIN "systems"."systems" ON "systems"."systems"."system_name" = "systems"."interfaces"."system_name" - WHERE "systems"."interface_addresses"."address" = input_address) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied on interface address %. You are not owner.',input_address; - END IF; - END IF; - - -- Remove address - DELETE FROM "systems"."interface_addresses" WHERE "address" = input_address; - - -- Done - PERFORM api.syslog('remove_interface_address:"'||input_address||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_interface_address(input_address inet) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_interface_address(input_address inet); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_interface_address(input_address inet) IS 'delete an interface address'; - - --- --- Name: remove_ip_range(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_ip_range(input_name text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "ip"."subnets" WHERE "subnet" = - (SELECT "subnet" FROM "ip"."ranges" WHERE "name" = input_range)) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission to delete range % denied. Not owner',input_name; - END IF; - END IF; - - -- Delete range - DELETE FROM "ip"."ranges" WHERE "name" = input_name; - - -- Done - PERFORM api.syslog('remove_ip_range:"'||input_name||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_ip_range(input_name text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_ip_range(input_name text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_ip_range(input_name text) IS 'Delete an existing IP range'; - - --- --- Name: remove_ip_subnet(cidr); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_ip_subnet(input_subnet cidr) RETURNS void - LANGUAGE plpgsql - AS $$ - DECLARE - RowCount INTEGER; - WasAuto BOOLEAN; - BEGIN - -- Check privileges - IF (api.get_current_user_level() !~* 'ADMIN') THEN - IF (SELECT "owner" FROM "ip"."subnets" WHERE "subnet" = input_subnet) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission to delete subnet % denied. Not owner',input_subnet; - END IF; - END IF; - - -- Delete RDNS zone - PERFORM api.remove_dns_zone(api.get_reverse_domain(input_subnet)); - - -- Delete subnet - DELETE FROM "ip"."subnets" WHERE "subnet" = input_subnet; - - -- Done - PERFORM api.syslog('remove_ip_subnet:"'||input_subnet||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_ip_subnet(input_subnet cidr) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_ip_subnet(input_subnet cidr); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_ip_subnet(input_subnet cidr) IS 'Delete/deactivate an existing subnet'; - - --- --- Name: remove_libvirt_domain(text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_libvirt_domain(input_host text, input_domain text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF (SELECT "owner" FROM "system"."systems" WHERE "system_name" = input_host) != api.get_current_user() THEN - RAISE EXCEPTION 'Only admins can remove VM hosts'; - END IF; - IF (SELECT "owner" FROM "system"."systems" WHERE "system_name" = input_domain) != api.get_current_user() THEN - RAISE EXCEPTION 'Only admins can remove VM hosts'; - END IF; - END IF; - - DELETE FROM "libvirt"."domains" WHERE "domain_name" = input_domain AND "host_name" = input_host; - END; -$$; - - -ALTER FUNCTION api.remove_libvirt_domain(input_host text, input_domain text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_libvirt_domain(input_host text, input_domain text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_libvirt_domain(input_host text, input_domain text) IS 'Remove a libvirt domain'; - - --- --- Name: remove_libvirt_host(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_libvirt_host(input_system text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Only admins can remove VM hosts'; - END IF; - - DELETE FROM "libvirt"."hosts" WHERE "system_name" = input_system; - END; -$$; - - -ALTER FUNCTION api.remove_libvirt_host(input_system text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_libvirt_host(input_system text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_libvirt_host(input_system text) IS 'Remove libvirt connection credentials for a system'; - - --- --- Name: remove_libvirt_platform(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_libvirt_platform(input_name text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Only admins can remove VM hosts'; - END IF; - - DELETE FROM "libvirt"."platforms" WHERE "platform_name" = input_name; - END; -$$; - - -ALTER FUNCTION api.remove_libvirt_platform(input_name text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_libvirt_platform(input_name text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_libvirt_platform(input_name text) IS 'Remove libvirt platform'; - - --- --- Name: remove_network_snmp(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_network_snmp(input_system text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF (SELECT "owner" FROM "systems"."systems" WHERE "system_name" = input_system) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied: you are not owner'; - END IF; - END IF; - - -- Create it - DELETE FROM "network"."snmp" WHERE "system_name" = input_system; - - -- Done - PERFORM api.syslog('remove_network_snmp:"'||input_system||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_network_snmp(input_system text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_network_snmp(input_system text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_network_snmp(input_system text) IS 'Remove credentials for a system'; - - --- --- Name: remove_platform(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_platform(input_name text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission denied: Only admins can remove platforms'; - END IF; - - DELETE FROM "systems"."platforms" WHERE "platform_name" = input_name; - END; -$$; - - -ALTER FUNCTION api.remove_platform(input_name text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_platform(input_name text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_platform(input_name text) IS 'Remove a platform'; - - --- --- Name: remove_range_group(text, text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_range_group(input_range text, input_group text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - -- Privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Only admins can assign range resources to groups'; - END IF; - - -- Remove - DELETE FROM "ip"."range_groups" WHERE "range_name" = input_range AND "group_name" = input_group; - - -- Done - PERFORM api.syslog('remove_range_group:"'||input_range||'","'||input_group||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_range_group(input_range text, input_group text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_range_group(input_range text, input_group text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_range_group(input_range text, input_group text) IS 'Remove a range group'; - - --- --- Name: remove_site_configuration(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_site_configuration(input_directive text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission denied. Only admins can remove site directives'; - END IF; - - -- Create directive - DELETE FROM "management"."configuration" WHERE "option" = input_directive; - - -- Done - PERFORM api.syslog('remove_site_configuration:"'||input_directive||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_site_configuration(input_directive text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_site_configuration(input_directive text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_site_configuration(input_directive text) IS 'Remove a site configuration directive'; - - --- --- Name: remove_system(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_system(input_system_name text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - IF (SELECT "owner" FROM "systems"."systems" WHERE "system_name" = input_system_name) != api.get_current_user() THEN - RAISE EXCEPTION 'Permission denied on system %. You are not owner.',input_system_name; - END IF; - END IF; - - -- Remove system - DELETE FROM "systems"."systems" WHERE "system_name" = input_system_name; - - -- Done - PERFORM api.syslog('remove_system:"'||input_system_name||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_system(input_system_name text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_system(input_system_name text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_system(input_system_name text) IS 'Delete an existing system'; - - --- --- Name: remove_users_systems(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_users_systems(username text) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - - -- Check privileges - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Permission denied: Only admins can remove all systems from a user'; - END IF; - - -- Perform delete - DELETE FROM "systems"."systems" WHERE "owner" = username; - - -- Done - PERFORM api.syslog('remove_users_systems:"'||username||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_users_systems(username text) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_users_systems(username text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_users_systems(username text) IS 'Remove all systems owned by a user'; - - --- --- Name: remove_vlan(text, integer); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION remove_vlan(input_datacenter text, input_vlan integer) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - IF api.get_current_user_level() !~* 'ADMIN' THEN - RAISE EXCEPTION 'Only admins can remove VLANs'; - END IF; - - DELETE FROM "network"."vlans" WHERE "datacenter" = input_datacenter AND "vlan" = input_vlan; - PERFORM api.syslog('remove_vlan:"'||input_datacenter||'","'||input_vlan||'"'); - END; -$$; - - -ALTER FUNCTION api.remove_vlan(input_datacenter text, input_vlan integer) OWNER TO starrs_admin; - --- --- Name: FUNCTION remove_vlan(input_datacenter text, input_vlan integer); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION remove_vlan(input_datacenter text, input_vlan integer) IS 'Remove a VLAN'; - - --- --- Name: renew_interface_address(inet); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION renew_interface_address(input_address inet) RETURNS void - LANGUAGE plpgsql - AS $$ - BEGIN - UPDATE "systems"."interface_addresses" - SET "renew_date" = date(('now'::text)::date + (SELECT "renew_interval" FROM "management"."groups" JOIN "systems"."systems" ON "systems"."systems"."group" = "management"."groups"."group" WHERE "system_name" = api.get_interface_address_system(input_address))) - WHERE "address" = input_address; - - END; -$$; - - -ALTER FUNCTION api.renew_interface_address(input_address inet) OWNER TO starrs_admin; - --- --- Name: FUNCTION renew_interface_address(input_address inet); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION renew_interface_address(input_address inet) IS 'renew an interface address registration for another interval'; - - --- --- Name: resolve(text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION resolve(text) RETURNS inet - LANGUAGE plperlu - AS $_$ - use strict; - use warnings; - use Socket qw(inet_ntoa); - - my $hostname = shift() or die "Unable to get name argument"; - my ($name,$aliases,$addrtype,$length,@addrs) = gethostbyname($hostname); - return inet_ntoa($addrs[0]); -$_$; - - -ALTER FUNCTION api.resolve(text) OWNER TO postgres; - --- --- Name: send_renewal_email(text, inet, text, text, text, text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION send_renewal_email(text, inet, text, text, text, text) RETURNS void - LANGUAGE plperlu - AS $_$ - use strict; - use warnings; - use Net::SMTP; - use POSIX; - - my $email = shift(@_) or die "Unable to get email"; - my $address = shift(@_) or die "Unable to get address"; - my $system = shift(@_) or die "Unable to get system"; - my $domain = shift(@_) or die "Unable to get mail domain"; - my $url = shift(@_) or die "Unable to get URL"; - my $mailserver = shift(@_) or die "Unable to get mailserver"; - - my $smtp = Net::SMTP->new($mailserver); - - if(!$smtp) { die "Unable to connect to \"$mailserver\"\n"; } - - $smtp->mail("starrs-noreply\@$domain"); - $smtp->recipient("$email"); - $smtp->data; - $smtp->datasend("Date: " . strftime("%a, %d %b %Y %H:%M:%S %z", localtime) . "\n"); - $smtp->datasend("From: starrs-noreply\@$domain\n"); - $smtp->datasend("To: $email\n"); - $smtp->datasend("Subject: STARRS Renewal Notification - $address\n"); - $smtp->datasend("\n"); - $smtp->datasend("Your registered address $address on system $system will expire in fewer than 7 days and may be removed from STARRS automatically. You can click $url/addresses/viewrenew to renew your address(es). Alternatively you can navigate to the Interface Address view and click the Renew button. If you have any questions, please see your local system administrator."); - - $smtp->datasend; - $smtp->quit; -$_$; - - -ALTER FUNCTION api.send_renewal_email(text, inet, text, text, text, text) OWNER TO postgres; - --- --- Name: FUNCTION send_renewal_email(text, inet, text, text, text, text); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION send_renewal_email(text, inet, text, text, text, text) IS 'Send an email to a user saying their address is about to expire'; - - --- --- Name: syslog(text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION syslog(input_message text) RETURNS void - LANGUAGE plperlu - AS $_$ - #!/usr/bin/perl - use strict; - use warnings; - use Sys::Syslog qw( :DEFAULT setlogsock); - - #my $sev = shift(@_) or die "Unable to get severity"; - my $sev = "info"; - my $msg = shift(@_) or die "Unable to get message."; - my $facility = spi_exec_query("SELECT api.get_site_configuration('SYSLOG_FACILITY')")->{rows}[0]->{"get_site_configuration"}; - my $user= spi_exec_query("SELECT api.get_current_user()")->{rows}[0]->{"get_current_user"}; - setlogsock('unix'); - openlog("STARRS",'',$facility); - syslog($sev, "$user $msg"); - closelog; -$_$; - - -ALTER FUNCTION api.syslog(input_message text) OWNER TO postgres; - --- --- Name: FUNCTION syslog(input_message text); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION syslog(input_message text) IS 'Log to syslog'; - - --- --- Name: validate_domain(text, text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION validate_domain(hostname text, domain text) RETURNS boolean - LANGUAGE plperlu - AS $_X$ - use strict; - use warnings; - use Data::Validate::Domain qw(is_domain); - # die("LOLZ"); - - # Usage: PERFORM api.validate_domain([hostname OR NULL],[domain OR NULL]); - - # Declare the string to check later on - my $domain; - - # This script can deal with just domain validation rather than host-domain. Note that the - # module this depends on requires a valid TLD, so one is picked for this purpose. - if (!$_[0]) - { - # We are checking a domain name only - $domain = $_[1]; - } - elsif (!$_[1]) - { - # We are checking a hostname only - $domain = "$_[0].me"; - } - else - { - # We have enough for a FQDN - $domain = "$_[0].$_[1]"; - } - - if($_[0] eq "0") { - return 'TRUE'; - } - - # Return a boolean value of whether the input forms a valid domain - if (is_domain($domain)) - { - return 'TRUE'; - } - else - { - # This module sucks and should be disabled - #return 'TRUE'; - # Seems to be working normally... Keep an eye on your domain validation - return 'FALSE'; - } -$_X$; - - -ALTER FUNCTION api.validate_domain(hostname text, domain text) OWNER TO postgres; - --- --- Name: FUNCTION validate_domain(hostname text, domain text); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION validate_domain(hostname text, domain text) IS 'Validate hostname, domain, FQDN based on known rules. Requires Perl module'; - - --- --- Name: validate_name(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION validate_name(input text) RETURNS text - LANGUAGE plpgsql - AS $$ - DECLARE - BadCrap TEXT; - BEGIN - BadCrap = regexp_replace(input, E'[a-z0-9\:\_\/ ]*\-*', '', 'gi'); - IF BadCrap != '' THEN - RAISE EXCEPTION 'Invalid characters detected in string "%"',input; - END IF; - IF input = '' THEN - RAISE EXCEPTION 'Name cannot be blank'; - END IF; - RETURN input; - END; -$$; - - -ALTER FUNCTION api.validate_name(input text) OWNER TO starrs_admin; - --- --- Name: FUNCTION validate_name(input text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION validate_name(input text) IS 'Allow certain characters for names'; - - --- --- Name: validate_nospecial(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION validate_nospecial(input text) RETURNS text - LANGUAGE plpgsql - AS $$ - DECLARE - BadCrap TEXT; - BEGIN - BadCrap = regexp_replace(input, E'[a-z0-9]*', '', 'gi'); - IF BadCrap != '' THEN - RAISE EXCEPTION 'Invalid characters detected in string "%"',input; - END IF; - RETURN input; - END; -$$; - - -ALTER FUNCTION api.validate_nospecial(input text) OWNER TO starrs_admin; - --- --- Name: FUNCTION validate_nospecial(input text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION validate_nospecial(input text) IS 'Block all special characters'; - - --- --- Name: validate_soa_contact(text); Type: FUNCTION; Schema: api; Owner: starrs_admin --- - -CREATE FUNCTION validate_soa_contact(input text) RETURNS boolean - LANGUAGE plpgsql - AS $$ - DECLARE - BadCrap TEXT; - BEGIN - BadCrap = regexp_replace(input, E'[a-z0-9\.]*\-*', '', 'gi'); - IF BadCrap != '' THEN - RAISE EXCEPTION 'Invalid characters detected in string "%"',input; - END IF; - IF input = '' THEN - RAISE EXCEPTION 'Contact cannot be blank'; - END IF; - RETURN TRUE; - END; -$$; - - -ALTER FUNCTION api.validate_soa_contact(input text) OWNER TO starrs_admin; - --- --- Name: FUNCTION validate_soa_contact(input text); Type: COMMENT; Schema: api; Owner: starrs_admin --- - -COMMENT ON FUNCTION validate_soa_contact(input text) IS 'Ensure that the SOA contact is properly formatted'; - - --- --- Name: validate_srv(text); Type: FUNCTION; Schema: api; Owner: postgres --- - -CREATE FUNCTION validate_srv(text) RETURNS boolean - LANGUAGE plperl - AS $_X$ - my $srv = $_[0]; - my @parts = split('\.',$srv); - - # Check for two parts: the service and the transport - if (scalar(@parts) ne 2) - { - die "Improper number of parts in record\n Please use _service._protocol format!\n"; - } - - # Define parts of the record - my $service = $parts[0]; - my $transport = $parts[1]; - - # Check if transport is valid - if ($transport !~ m/_tcp|_udp/i) - { - die "Protocol must be _tcp or _udp!"; - } - - # Check that service is valid - if ($service !~ m/^_[\w-]+$/i) - { - die "Invalid Service Name! (Did you forget a leading underscore?)"; - } - - # Good! - return "true"; -$_X$; - - -ALTER FUNCTION api.validate_srv(text) OWNER TO postgres; - --- --- Name: FUNCTION validate_srv(text); Type: COMMENT; Schema: api; Owner: postgres --- - -COMMENT ON FUNCTION validate_srv(text) IS 'Validate SRV records'; - - -SET search_path = dns, pg_catalog; - --- --- Name: a_insert(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION a_insert() RETURNS trigger - LANGUAGE plpgsql - AS $$ - DECLARE - RowCount INTEGER; - BEGIN - /* - -- Check for zone mismatch - SELECT COUNT(*) INTO RowCount - FROM "ip"."subnets" - WHERE "ip"."subnets"."zone" = NEW."zone" - AND NEW."address" << "ip"."subnets"."subnet"; - IF (RowCount < 1) THEN - RAISE EXCEPTION 'IP address and DNS Zone do not match (%, %)',NEW."address",NEW."zone"; - END IF; - */ - -- Autofill type - - RETURN NEW; - END; -$$; - - -ALTER FUNCTION dns.a_insert() OWNER TO starrs_admin; - --- --- Name: FUNCTION a_insert(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION a_insert() IS 'Creating a new A or AAAA record'; - - --- --- Name: a_update(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION a_update() RETURNS trigger - LANGUAGE plpgsql - AS $$ - DECLARE - RowCount INTEGER; - BEGIN - -- Address/Zone mismatch - IF NEW."address" != OLD."address" THEN - SELECT COUNT(*) INTO RowCount - FROM "ip"."subnets" - WHERE "ip"."subnets"."zone" = NEW."zone" - AND NEW."address" << "ip"."subnets"."subnet"; - IF (RowCount < 1) THEN - RAISE EXCEPTION 'IP address and DNS Zone do not match (%, %)',NEW."address",NEW."zone"; - END IF; - - -- Autofill Type - END IF; - - -- New zone mismatch - IF NEW."zone" != OLD."zone" THEN - SELECT COUNT(*) INTO RowCount - FROM "ip"."subnets" - WHERE "ip"."subnets"."zone" = NEW."zone" - AND NEW."address" << "ip"."subnets"."subnet"; - IF (RowCount < 1) THEN - RAISE EXCEPTION 'IP address and DNS Zone do not match (%, %)',NEW."address",NEW."zone"; - END IF; - END IF; - - RETURN NEW; - END; -$$; - - -ALTER FUNCTION dns.a_update() OWNER TO starrs_admin; - --- --- Name: FUNCTION a_update(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION a_update() IS 'Update an existing A or AAAA record'; - - --- --- Name: cname_insert(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION cname_insert() RETURNS trigger - LANGUAGE plpgsql - AS $$ - DECLARE - RowCount INTEGER; - BEGIN - -- Check if alias name already exists - SELECT COUNT(*) INTO RowCount - FROM "dns"."a" - WHERE "dns"."a"."hostname" = NEW."alias"; - IF (RowCount > 0) THEN - RAISE EXCEPTION 'Alias name (%) already exists',NEW."alias"; - END IF; - - SELECT COUNT(*) INTO RowCount - FROM "dns"."srv" - WHERE "dns"."srv"."alias" = NEW."alias"; - IF (RowCount > 0) THEN - RAISE EXCEPTION 'Alias name (%) already exists as a SRV',NEW."alias"; - END IF; - - -- Autopopulate address - NEW."address" := dns.dns_autopopulate_address(NEW."hostname",NEW."zone"); - - RETURN NEW; - END; -$$; - - -ALTER FUNCTION dns.cname_insert() OWNER TO starrs_admin; - --- --- Name: FUNCTION cname_insert(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION cname_insert() IS 'Check if the alias already exists as an address record'; - - --- --- Name: cname_update(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION cname_update() RETURNS trigger - LANGUAGE plpgsql - AS $$ - DECLARE - RowCount INTEGER; - BEGIN - -- Check if alias name already exists - IF NEW."alias" != OLD."alias" THEN - SELECT COUNT(*) INTO RowCount - FROM "dns"."a" - WHERE "dns"."a"."hostname" = NEW."alias"; - IF (RowCount > 0) THEN - RAISE EXCEPTION 'Alias name (%) already exists',NEW."alias"; - END IF; - - SELECT COUNT(*) INTO RowCount - FROM "dns"."srv" - WHERE "dns"."srv"."alias" = NEW."alias"; - IF (RowCount > 0) THEN - RAISE EXCEPTION 'Alias name (%) already exists as a SRV',NEW."alias"; - END IF; - END IF; - - -- Autopopulate address - IF NEW."address" != OLD."address" THEN - NEW."address" := dns.dns_autopopulate_address(NEW."hostname",NEW."zone"); - END IF; - - RETURN NEW; - END; -$$; - - -ALTER FUNCTION dns.cname_update() OWNER TO starrs_admin; - --- --- Name: FUNCTION cname_update(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION cname_update() IS 'Check if the new alias already exists as an address record'; - - --- --- Name: dns_autopopulate_address(text, text); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION dns_autopopulate_address(input_hostname text, input_zone text) RETURNS inet - LANGUAGE plpgsql - AS $$ - DECLARE - address INET; - BEGIN - SELECT "dns"."a"."address" INTO address - FROM "dns"."a" - WHERE "dns"."a"."hostname" = input_hostname - AND "dns"."a"."zone" = input_zone LIMIT 1; - - IF address IS NULL THEN - RAISE EXCEPTION 'Unable to find address for given host % and zone %',input_hostname,input_zone; - ELSE - RETURN address; - END IF; - END; -$$; - - -ALTER FUNCTION dns.dns_autopopulate_address(input_hostname text, input_zone text) OWNER TO starrs_admin; - --- --- Name: FUNCTION dns_autopopulate_address(input_hostname text, input_zone text); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION dns_autopopulate_address(input_hostname text, input_zone text) IS 'Fill in the address portion of the foreign key relationship'; - - --- --- Name: mx_insert(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION mx_insert() RETURNS trigger - LANGUAGE plpgsql - AS $$ - BEGIN - NEW."address" := dns.dns_autopopulate_address(NEW."hostname",NEW."zone"); - RETURN NEW; - END; -$$; - - -ALTER FUNCTION dns.mx_insert() OWNER TO starrs_admin; - --- --- Name: FUNCTION mx_insert(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION mx_insert() IS 'Create new MX record'; - - --- --- Name: mx_update(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION mx_update() RETURNS trigger - LANGUAGE plpgsql - AS $$ - BEGIN - IF NEW."address" != OLD."address" THEN - NEW."address" := dns.dns_autopopulate_address(NEW."hostname",NEW."zone"); - END IF; - RETURN NEW; - END; -$$; - - -ALTER FUNCTION dns.mx_update() OWNER TO starrs_admin; - --- --- Name: FUNCTION mx_update(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION mx_update() IS 'Modify a MX record'; - - --- --- Name: ns_query_delete(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION ns_query_delete() RETURNS trigger - LANGUAGE plpgsql - AS $_$ - DECLARE - ReturnCode TEXT; -- Return code from the nsupdate function - DnsKeyName TEXT; -- The DNS keyname to sign with - DnsKey TEXT; -- The DNS key to sign with - DnsServer INET; -- The nameserver to send the update to - DnsRecord TEXT; -- The formatted string that is the record - BEGIN - IF (SELECT "ddns" FROM "dns"."zones" WHERE "dns"."zones"."zone" = OLD."zone") IS FALSE THEN - RETURN OLD; - END IF; - - -- If this is a forward zone: - IF (SELECT "forward" FROM "dns"."zones" WHERE "zone" = OLD."zone") IS TRUE THEN - SELECT "dns"."keys"."keyname","dns"."keys"."key",api.resolve("dns"."soa"."nameserver") - INTO DnsKeyName, DnsKey, DnsServer - FROM "dns"."zones" - JOIN "dns"."keys" ON "dns"."keys"."keyname" = "dns"."zones"."keyname" - JOIN "dns"."soa" ON "dns"."soa"."zone" = "dns"."zones"."zone" - WHERE "dns"."zones"."zone" = OLD."zone"; - -- If this is a reverse zone: - ELSE - SELECT "dns"."keys"."keyname","dns"."keys"."key",api.resolve("dns"."soa"."nameserver") - INTO DnsKeyName, DnsKey, DnsServer - FROM "dns"."zones" - JOIN "dns"."keys" ON "dns"."keys"."keyname" = "dns"."zones"."keyname" - JOIN "dns"."soa" ON "dns"."soa"."zone" = "dns"."zones"."zone" - WHERE "dns"."ns"."zone" = (SELECT "ip"."subnets"."zone" FROM "ip"."subnets" WHERE api.get_reverse_domain("subnet") = OLD."zone"); - END IF; - - -- Just make sure no-one is forcing a bogus type - IF OLD."type" !~* '^NS$' THEN - RAISE EXCEPTION 'Trying to create a non-NS record in an NS table!'; - END IF; - - -- Create and fire off the update - DnsRecord := OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||OLD."nameserver"; - ReturnCode := api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - - -- Check for result - IF ReturnCode != '0' THEN - RAISE EXCEPTION 'DNS Error: % when performing NS-DELETE %',ReturnCode,DnsRecord; - END IF; - - -- Done! - RETURN OLD; - END; -$_$; - - -ALTER FUNCTION dns.ns_query_delete() OWNER TO starrs_admin; - --- --- Name: FUNCTION ns_query_delete(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION ns_query_delete() IS 'Delete an old NS record from the server'; - - --- --- Name: ns_query_insert(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION ns_query_insert() RETURNS trigger - LANGUAGE plpgsql - AS $_$ - DECLARE - ReturnCode TEXT; -- Return code from the nsupdate function - DnsKeyName TEXT; -- The DNS keyname to sign with - DnsKey TEXT; -- The DNS key to sign with - DnsServer INET; -- The nameserver to send the update to - DnsRecord TEXT; -- The formatted string that is the record - BEGIN - IF (SELECT "ddns" FROM "dns"."zones" WHERE "dns"."zones"."zone" = NEW."zone") IS FALSE THEN - RETURN NEW; - END IF; - - -- If this is a forward zone: - IF (SELECT "forward" FROM "dns"."zones" WHERE "zone" = NEW."zone") IS TRUE THEN - SELECT "dns"."keys"."keyname","dns"."keys"."key","address" - INTO DnsKeyName, DnsKey, DnsServer - FROM "dns"."ns" - JOIN "dns"."zones" ON "dns"."ns"."zone" = "dns"."zones"."zone" - JOIN "dns"."keys" ON "dns"."zones"."keyname" = "dns"."keys"."keyname" - WHERE "dns"."ns"."zone" = NEW."zone" AND "dns"."ns"."nameserver" IN (SELECT "nameserver" FROM "dns"."soa" WHERE "dns"."soa"."zone" = NEW."zone"); - -- If this is a reverse zone: - ELSE - SELECT "dns"."keys"."keyname","dns"."keys"."key","dns"."ns"."address" - INTO DnsKeyName, DnsKey, DnsServer - FROM "dns"."ns" - JOIN "dns"."zones" ON "dns"."ns"."zone" = "dns"."zones"."zone" - JOIN "dns"."keys" ON "dns"."zones"."keyname" = "dns"."keys"."keyname" - JOIN "dns"."soa" ON "dns"."soa"."zone" = "dns"."ns"."zone" - WHERE "dns"."ns"."nameserver" = "dns"."soa"."nameserver" - AND "dns"."ns"."zone" = (SELECT "ip"."subnets"."zone" FROM "ip"."subnets" WHERE api.get_reverse_domain("subnet") = NEW."zone"); - END IF; - - -- Just make sure no-one is forcing a bogus type - IF NEW."type" !~* '^NS$' THEN - RAISE EXCEPTION 'Trying to create a non-NS record in an NS table!'; - END IF; - - -- Create and fire off the update - DnsRecord := NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||NEW."nameserver"; - ReturnCode := api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - - -- Check for result - IF ReturnCode != '0' THEN - RAISE EXCEPTION 'DNS Error: % when performing %',ReturnCode,DnsRecord; - END IF; - - -- Done! - RETURN NEW; - END; -$_$; - - -ALTER FUNCTION dns.ns_query_insert() OWNER TO starrs_admin; - --- --- Name: FUNCTION ns_query_insert(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION ns_query_insert() IS 'Update the nameserver with a new NS record'; - - --- --- Name: ns_query_update(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION ns_query_update() RETURNS trigger - LANGUAGE plpgsql - AS $_$ - DECLARE - ReturnCode TEXT; -- Return code from the nsupdate function - DnsKeyName TEXT; -- The DNS keyname to sign with - DnsKey TEXT; -- The DNS key to sign with - DnsServer INET; -- The nameserver to send the update to - DnsRecord TEXT; -- The formatted string that is the record - BEGIN - IF (SELECT "ddns" FROM "dns"."zones" WHERE "dns"."zones"."zone" = OLD."zone") IS FALSE THEN - RETURN NEW; - END IF; - - -- If this is a forward zone: - IF (SELECT "forward" FROM "dns"."zones" WHERE "zone" = NEW."zone") IS TRUE THEN - SELECT "dns"."keys"."keyname","dns"."keys"."key",api.resolve("dns"."soa"."nameserver") - INTO DnsKeyName, DnsKey, DnsServer - FROM "dns"."zones" - JOIN "dns"."keys" ON "dns"."keys"."keyname" = "dns"."zones"."keyname" - JOIN "dns"."soa" ON "dns"."soa"."zone" = "dns"."zones"."zone" - WHERE "dns"."zones"."zone" = NEW."zone"; - -- If this is a reverse zone: - ELSE - SELECT "dns"."keys"."keyname","dns"."keys"."key",api.resolve("dns"."soa"."nameserver") - INTO DnsKeyName, DnsKey, DnsServer - FROM "dns"."zones" - JOIN "dns"."keys" ON "dns"."keys"."keyname" = "dns"."zones"."keyname" - JOIN "dns"."soa" ON "dns"."soa"."zone" = "dns"."zones"."zone" - WHERE "dns"."ns"."zone" = (SELECT "ip"."subnets"."zone" FROM "ip"."subnets" WHERE api.get_reverse_domain("subnet") = NEW."zone"); - END IF; - - -- Just make sure no-one is forcing a bogus type - IF NEW."type" !~* '^NS$' THEN - RAISE EXCEPTION 'Trying to create a non-NS record in an NS table!'; - END IF; - - -- Delete the record first - DnsRecord := OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||OLD."nameserver"; - ReturnCode := api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - - -- Check for result - IF ReturnCode != '0' THEN - RAISE EXCEPTION 'DNS Error: % when performing NS-UPDATE-DELETE %',ReturnCode,DnsRecord; - END IF; - - IF (SELECT "ddns" FROM "dns"."zones" WHERE "dns"."zones"."zone" = NEW."zone") IS FALSE THEN - RETURN NEW; - END IF; - - -- Create and fire off the update - DnsRecord := NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||NEW."nameserver"; - ReturnCode := api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - - -- Check for result - IF ReturnCode != '0' THEN - RAISE EXCEPTION 'DNS Error: % when performing NS-UPDATE-INSERT %',ReturnCode,DnsRecord; - END IF; - - -- Done! - RETURN NEW; - END; -$_$; - - -ALTER FUNCTION dns.ns_query_update() OWNER TO starrs_admin; - --- --- Name: FUNCTION ns_query_update(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION ns_query_update() IS 'Update the nameserver with a new NS record'; - - --- --- Name: queue_delete(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION queue_delete() RETURNS trigger - LANGUAGE plpgsql - AS $_$ - DECLARE - ReturnCode TEXT; - DnsKeyName TEXT; - DnsKey TEXT; - DnsServer INET; - DnsRecord TEXT; - RevZone TEXT; - RevSubnet CIDR; - BEGIN - IF (SELECT "ddns" FROM "dns"."zones" WHERE "dns"."zones"."zone" = OLD."zone") IS FALSE THEN - RETURN OLD; - END IF; - - - -- This needs cleaned up a lot. See github bug #211 for more details. This fix works but is - -- not exactly great. - IF true THEN - - SELECT "dns"."keys"."keyname","dns"."keys"."key",api.resolve("dns"."soa"."nameserver") - INTO DnsKeyName, DnsKey, DnsServer - FROM "dns"."zones" - JOIN "dns"."keys" ON "dns"."keys"."keyname" = "dns"."zones"."keyname" - JOIN "dns"."soa" ON "dns"."soa"."zone" = "dns"."zones"."zone" - WHERE "dns"."zones"."zone" = OLD."zone"; - - IF OLD."type" ~* '^A|AAAA$' THEN - --NULL hostname means zone address - IF OLD."hostname" IS NULL THEN - DnsRecord := OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||host(OLD."address"); - ReturnCode := api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - ELSE - -- Do the forward record first - DnsRecord := OLD."hostname"||'.'||OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||host(OLD."address"); - ReturnCode := api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - - -- Check for errors - IF ReturnCode != '0' THEN - RAISE EXCEPTION 'DNS Error: % when performing %',ReturnCode,DnsRecord; - END IF; - - -- Get the proper zone for the reverse A record - SELECT "zone" INTO RevZone - FROM "ip"."subnets" - WHERE OLD."address" << "subnet"; - - -- Get the subnet - SELECT "subnet" INTO RevSubnet - FROM "ip"."subnets" - WHERE OLD."address" << "subnet"; - - -- If it is in this domain, add the reverse entry - IF RevZone = OLD."zone" AND OLD."reverse" IS TRUE AND NOT OLD."address" << api.get_site_configuration('DYNAMIC_SUBNET')::cidr THEN - DnsRecord := api.get_reverse_domain(OLD."address")||' '||OLD."ttl"||' PTR '||OLD."hostname"||'.'||OLD."zone"||'.'; - ReturnCode := api.nsupdate(api.get_reverse_domain(RevSubnet),DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - END IF; - END IF; - - ELSEIF OLD."type" ~* '^NS$' THEN - DnsRecord := OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||OLD."nameserver"; - ReturnCode := api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - ELSEIF OLD."type" ~* '^MX$' THEN - DnsRecord := OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||OLD."preference"||' '||OLD."hostname"||'.'||OLD."zone"; - ReturnCode := api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - ELSEIF OLD."type" ~* '^SRV$' THEN - DnsRecord := OLD."alias"||'.'||OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||OLD."priority"||' '||OLD."weight"||' '||OLD."port"||' '||OLD."hostname"||'.'||OLD."zone"; - ReturnCode := Returncode||api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - ELSEIF OLD."type" ~* '^CNAME$' THEN - DnsRecord := OLD."alias"||'.'||OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||OLD."hostname"||'.'||OLD."zone"; - ReturnCode := Returncode||api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - ELSEIF OLD."type" ~* '^TXT$' THEN - -- For zone TXT records - IF OLD."hostname" IS NULL THEN - DnsRecord := OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' "'||OLD."text"||'"'; - ELSE - DnsRecord := OLD."hostname"||'.'||OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' "'||OLD."text"||'"'; - END IF; - ReturnCode := api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - END IF; - - IF ReturnCode != '0' THEN - RAISE EXCEPTION 'DNS Error: % when performing %',ReturnCode,DnsRecord; - END IF; - ELSE - SELECT "dns"."keys"."keyname","dns"."keys"."key",api.resolve("dns"."soa"."nameserver") - INTO DnsKeyName, DnsKey, DnsServer - FROM "dns"."zones" - JOIN "dns"."keys" ON "dns"."keys"."keyname" = "dns"."zones"."keyname" - JOIN "dns"."soa" ON "dns"."soa"."zone" = "dns"."zones"."zone" - WHERE "dns"."zones"."zone" = OLD."zone"; - - IF OLD."type" ~* '^NS$' THEN - DnsRecord := OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||OLD."nameserver"; - ReturnCode := api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - ELSEIF OLD."type" ~* '^MX$' THEN - DnsRecord := OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||OLD."preference"||' '||OLD."hostname"||'.'||OLD."zone"; - ReturnCode := api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - ELSEIF OLD."type" ~* '^SRV$' THEN - DnsRecord := OLD."alias"||'.'||OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||OLD."priority"||' '||OLD."weight"||' '||OLD."port"||' '||OLD."hostname"||'.'||OLD."zone"; - ReturnCode := Returncode||api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - ELSEIF OLD."type" ~* '^CNAME$' THEN - DnsRecord := OLD."alias"||'.'||OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||OLD."hostname"||'.'||OLD."zone"; - ReturnCode := Returncode||api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - ELSEIF OLD."type" ~* '^TXT$' THEN - -- For zone TXT records - IF OLD."hostname" IS NULL THEN - DnsRecord := OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' "'||OLD."text"||'"'; - ELSE - DnsRecord := OLD."hostname"||'.'||OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' "'||OLD."text"||'"'; - END IF; - ReturnCode := api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - END IF; - - IF ReturnCode != '0' THEN - RAISE EXCEPTION 'DNS Error: % when performing %',ReturnCode,DnsRecord; - END IF; - END IF; - - RETURN OLD; - END; -$_$; - - -ALTER FUNCTION dns.queue_delete() OWNER TO starrs_admin; - --- --- Name: FUNCTION queue_delete(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION queue_delete() IS 'Add a delete directive to the queue'; - - --- --- Name: queue_insert(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION queue_insert() RETURNS trigger - LANGUAGE plpgsql - AS $_$ - DECLARE - ReturnCode TEXT; - DnsKeyName TEXT; - DnsKey TEXT; - DnsServer INET; - DnsRecord TEXT; - RevZone TEXT; - RevSubnet CIDR; - BEGIN - IF (SELECT "ddns" FROM "dns"."zones" WHERE "dns"."zones"."zone" = NEW."zone") IS FALSE THEN - RETURN NEW; - END IF; - - IF (SELECT "config" FROM api.get_system_interface_address(NEW."address")) ~* 'static|autoconf' THEN - SELECT "dns"."keys"."keyname","dns"."keys"."key",api.resolve("dns"."soa"."nameserver") - INTO DnsKeyName, DnsKey, DnsServer - FROM "dns"."zones" - JOIN "dns"."keys" ON "dns"."keys"."keyname" = "dns"."zones"."keyname" - JOIN "dns"."soa" ON "dns"."soa"."zone" = "dns"."zones"."zone" - WHERE "dns"."zones"."zone" = NEW."zone"; - - IF NEW."type" ~* '^A|AAAA$' THEN - --NULL hostname means zone address - IF NEW."hostname" IS NULL THEN - DnsRecord := NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||host(NEW."address"); - ReturnCode := api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - ELSE - -- Do the forward record first - DnsRecord := NEW."hostname"||'.'||NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||host(NEW."address"); - ReturnCode := api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - - -- Check for errors - IF ReturnCode != '0' THEN - RAISE EXCEPTION 'DNS Error: % when performing %',ReturnCode,DnsRecord; - END IF; - - -- Get the proper zone for the reverse A record - SELECT "zone" INTO RevZone - FROM "ip"."subnets" - WHERE NEW."address" << "subnet"; - - -- Get the subnet - SELECT "subnet" INTO RevSubnet - FROM "ip"."subnets" - WHERE NEW."address" << "subnet"; - - -- If it is in this domain, add the reverse entry - IF RevZone = NEW."zone" AND NEW."reverse" IS TRUE THEN - DnsRecord := api.get_reverse_domain(NEW."address")||' '||NEW."ttl"||' PTR '||NEW."hostname"||'.'||NEW."zone"||'.'; - ReturnCode := api.nsupdate(api.get_reverse_domain(RevSubnet),DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - END IF; - END IF; - - ELSEIF NEW."type" ~* '^NS$' THEN - DnsRecord := NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||NEW."nameserver"; - ReturnCode := api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - ELSEIF NEW."type" ~* '^MX$' THEN - DnsRecord := NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||NEW."preference"||' '||NEW."hostname"||'.'||NEW."zone"; - ReturnCode := api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - ELSEIF NEW."type" ~* '^SRV$' THEN - DnsRecord := NEW."alias"||'.'||NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||NEW."priority"||' '||NEW."weight"||' '||NEW."port"||' '||NEW."hostname"||'.'||NEW."zone"; - ReturnCode := api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - ELSEIF NEW."type" ~* '^CNAME$' THEN - DnsRecord := NEW."alias"||'.'||NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||NEW."hostname"||'.'||NEW."zone"; - ReturnCode := api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - ELSEIF NEW."type" ~* '^TXT$' THEN - -- For zone TXT records - IF NEW."hostname" IS NULL THEN - DnsRecord := NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' "'||NEW."text"||'"'; - ELSE - DnsRecord := NEW."hostname"||'.'||NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' "'||NEW."text"||'"'; - END IF; - ReturnCode := api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - END IF; - - IF ReturnCode != '0' THEN - RAISE EXCEPTION 'DNS Error: % when performing %',ReturnCode,DnsRecord; - END IF; - ELSE - SELECT "dns"."keys"."keyname","dns"."keys"."key",api.resolve("dns"."soa"."nameserver") - INTO DnsKeyName, DnsKey, DnsServer - FROM "dns"."zones" - JOIN "dns"."keys" ON "dns"."keys"."keyname" = "dns"."zones"."keyname" - JOIN "dns"."soa" ON "dns"."soa"."zone" = "dns"."zones"."zone" - WHERE "dns"."zones"."zone" = NEW."zone"; - - IF NEW."type" ~* '^NS$' THEN - DnsRecord := NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||NEW."nameserver"; - ReturnCode := api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - ELSEIF NEW."type" ~* '^MX$' THEN - DnsRecord := NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||NEW."preference"||' '||NEW."hostname"||'.'||NEW."zone"; - ReturnCode := api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - ELSEIF NEW."type" ~* '^SRV$' THEN - DnsRecord := NEW."alias"||'.'||NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||NEW."priority"||' '||NEW."weight"||' '||NEW."port"||' '||NEW."hostname"||'.'||NEW."zone"; - ReturnCode := api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - ELSEIF NEW."type" ~* '^CNAME$' THEN - DnsRecord := NEW."alias"||'.'||NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||NEW."hostname"||'.'||NEW."zone"; - ReturnCode := api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - ELSEIF NEW."type" ~* '^TXT$' THEN - -- For zone TXT records - IF NEW."hostname" IS NULL THEN - DnsRecord := NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' "'||NEW."text"||'"'; - ELSE - DnsRecord := NEW."hostname"||'.'||NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' "'||NEW."text"||'"'; - END IF; - ReturnCode := api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - END IF; - - IF ReturnCode != '0' THEN - RAISE EXCEPTION 'DNS Error: % when performing %',ReturnCode,DnsRecord; - END IF; - END IF; - - RETURN NEW; - END; -$_$; - - -ALTER FUNCTION dns.queue_insert() OWNER TO starrs_admin; - --- --- Name: FUNCTION queue_insert(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION queue_insert() IS 'Add an add directive to the queue'; - - --- --- Name: queue_update(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION queue_update() RETURNS trigger - LANGUAGE plpgsql - AS $_$ - DECLARE - ReturnCode TEXT; - DnsKeyName TEXT; - DnsKey TEXT; - DnsServer INET; - DnsRecord TEXT; - RevZone TEXT; - RevSubnet CIDR; - BEGIN - IF (SELECT "ddns" FROM "dns"."zones" WHERE "dns"."zones"."zone" = NEW."zone") IS FALSE THEN - RETURN NEW; - END IF; - - IF (SELECT "config" FROM api.get_system_interface_address(NEW."address")) ~* 'static|autoconf' THEN - SELECT "dns"."keys"."keyname","dns"."keys"."key",api.resolve("dns"."soa"."nameserver") - INTO DnsKeyName, DnsKey, DnsServer - FROM "dns"."zones" - JOIN "dns"."keys" ON "dns"."keys"."keyname" = "dns"."zones"."keyname" - JOIN "dns"."soa" ON "dns"."soa"."zone" = "dns"."zones"."zone" - WHERE "dns"."zones"."zone" = NEW."zone"; - - IF NEW."type" ~* '^A|AAAA$' THEN - --NULL hostname means zone address - IF NEW."hostname" IS NULL THEN - DnsRecord := OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||host(OLD."address"); - ReturnCode := api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - - DnsRecord := NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||host(NEW."address"); - ReturnCode := api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - ELSE - -- Do the forward record first - DnsRecord := OLD."hostname"||'.'||OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||host(OLD."address"); - ReturnCode := Returncode||api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - - -- Check for errors - IF ReturnCode != '0' THEN - RAISE EXCEPTION 'DNS Error: % when performing %',ReturnCode,DnsRecord; - END IF; - - -- Get the proper zone for the reverse A record - SELECT "zone" INTO RevZone - FROM "ip"."subnets" - WHERE OLD."address" << "subnet"; - - -- Get the subnet - SELECT "subnet" INTO RevSubnet - FROM "ip"."subnets" - WHERE OLD."address" << "subnet"; - - -- If it is in this domain, add the reverse entry - IF RevZone = OLD."zone" AND OLD."reverse" IS TRUE THEN - DnsRecord := api.get_reverse_domain(OLD."address")||' '||OLD."ttl"||' PTR '||OLD."hostname"||'.'||OLD."zone"||'.'; - ReturnCode := Returncode||api.nsupdate(api.get_reverse_domain(RevSubnet),DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - END IF; - - -- Do the forward record first - DnsRecord := NEW."hostname"||'.'||NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||host(NEW."address"); - ReturnCode := api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - - -- Check for errors - IF ReturnCode != '0' THEN - RAISE EXCEPTION 'DNS Error: % when performing %',ReturnCode,DnsRecord; - END IF; - - -- Get the proper zone for the reverse A record - SELECT "zone" INTO RevZone - FROM "ip"."subnets" - WHERE NEW."address" << "subnet"; - - -- Get the subnet - SELECT "subnet" INTO RevSubnet - FROM "ip"."subnets" - WHERE NEW."address" << "subnet"; - - -- If it is in this domain, add the reverse entry - IF RevZone = NEW."zone" AND NEW."reverse" IS TRUE THEN - DnsRecord := api.get_reverse_domain(NEW."address")||' '||NEW."ttl"||' PTR '||NEW."hostname"||'.'||NEW."zone"||'.'; - ReturnCode := Returncode||api.nsupdate(api.get_reverse_domain(RevSubnet),DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - END IF; - END IF; - - ELSEIF NEW."type" ~* '^NS$' THEN - DnsRecord := OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||OLD."nameserver"; - ReturnCode := Returncode||api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - - DnsRecord := NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||NEW."nameserver"; - ReturnCode := Returncode||api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - ELSEIF NEW."type" ~* '^MX$' THEN - DnsRecord := OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||OLD."preference"||' '||OLD."hostname"||'.'||OLD."zone"; - ReturnCode := Returncode||api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - - DnsRecord := NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||NEW."preference"||' '||NEW."hostname"||'.'||NEW."zone"; - ReturnCode := Returncode||api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - ELSEIF NEW."type" ~* '^SRV$' THEN - DnsRecord := OLD."alias"||'.'||OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||OLD."priority"||' '||OLD."weight"||' '||OLD."port"||' '||OLD."hostname"||'.'||OLD."zone"; - ReturnCode := Returncode||api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - - DnsRecord := NEW."alias"||'.'||NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||NEW."priority"||' '||NEW."weight"||' '||NEW."port"||' '||NEW."hostname"||'.'||NEW."zone"; - ReturnCode := Returncode||api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - ELSEIF NEW."type" ~* '^CNAME$' THEN - DnsRecord := OLD."alias"||'.'||OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||OLD."hostname"||'.'||OLD."zone"; - ReturnCode := Returncode||api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - - DnsRecord := NEW."alias"||'.'||NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||NEW."hostname"||'.'||NEW."zone"; - ReturnCode := Returncode||api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - ELSEIF NEW."type" ~* '^TXT$' THEN - -- For zone TXT records - IF OLD."hostname" IS NULL THEN - DnsRecord := OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' "'||OLD."text"||'"'; - ELSE - DnsRecord := OLD."hostname"||'.'||OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' "'||OLD."text"||'"'; - END IF; - ReturnCode := api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - - IF NEW."hostname" IS NULL THEN - DnsRecord := NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' "'||NEW."text"||'"'; - ELSE - DnsRecord := NEW."hostname"||'.'||NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' "'||NEW."text"||'"'; - END IF; - ReturnCode := api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - END IF; - ELSE - SELECT "dns"."keys"."keyname","dns"."keys"."key",api.resolve("dns"."soa"."nameserver") - INTO DnsKeyName, DnsKey, DnsServer - FROM "dns"."zones" - JOIN "dns"."keys" ON "dns"."keys"."keyname" = "dns"."zones"."keyname" - JOIN "dns"."soa" ON "dns"."soa"."zone" = "dns"."zones"."zone" - WHERE "dns"."zones"."zone" = NEW."zone"; - - IF NEW."type" ~* '^NS$' THEN - DnsRecord := OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||OLD."nameserver"; - ReturnCode := Returncode||api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - - DnsRecord := NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||NEW."nameserver"; - ReturnCode := Returncode||api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - ELSEIF NEW."type" ~* '^MX$' THEN - DnsRecord := OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||OLD."preference"||' '||OLD."hostname"||'.'||OLD."zone"; - ReturnCode := Returncode||api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - - DnsRecord := NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||NEW."preference"||' '||NEW."hostname"||'.'||NEW."zone"; - ReturnCode := Returncode||api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - ELSEIF NEW."type" ~* '^SRV$' THEN - DnsRecord := OLD."alias"||'.'||OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||OLD."priority"||' '||OLD."weight"||' '||OLD."port"||' '||OLD."hostname"||'.'||OLD."zone"; - ReturnCode := Returncode||api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - - DnsRecord := NEW."alias"||'.'||NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||NEW."priority"||' '||NEW."weight"||' '||NEW."port"||' '||NEW."hostname"||'.'||NEW."zone"; - ReturnCode := Returncode||api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - ELSEIF NEW."type" ~* '^CNAME$' THEN - DnsRecord := OLD."alias"||'.'||OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' '||OLD."hostname"||'.'||OLD."zone"; - ReturnCode := Returncode||api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - - DnsRecord := NEW."alias"||'.'||NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' '||NEW."hostname"||'.'||NEW."zone"; - ReturnCode := Returncode||api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - ELSEIF NEW."type" ~* '^TXT$' THEN - -- For zone TXT records - IF OLD."hostname" IS NULL THEN - DnsRecord := OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' "'||OLD."text"||'"'; - ELSE - DnsRecord := OLD."hostname"||'.'||OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' "'||OLD."text"||'"'; - END IF; - ReturnCode := api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - - IF NEW."hostname" IS NULL THEN - DnsRecord := NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' "'||NEW."text"||'"'; - ELSE - DnsRecord := NEW."hostname"||'.'||NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' "'||NEW."text"||'"'; - END IF; - ReturnCode := api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - END IF; - - IF ReturnCode != '0' THEN - RAISE EXCEPTION 'DNS Error: % when performing %',ReturnCode,DnsRecord; - END IF; - END IF; - RETURN NEW; - END; -$_$; - - -ALTER FUNCTION dns.queue_update() OWNER TO starrs_admin; - --- --- Name: FUNCTION queue_update(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION queue_update() IS 'Add a delete then add directive to the queue'; - - --- --- Name: srv_insert(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION srv_insert() RETURNS trigger - LANGUAGE plpgsql - AS $$ - DECLARE - RowCount INTEGER; - BEGIN - -- Check if alias name already exists - SELECT COUNT(*) INTO RowCount - FROM "dns"."a" - WHERE "dns"."a"."hostname" = NEW."alias"; - IF (RowCount > 0) THEN - RAISE EXCEPTION 'Alias name (%) already exists',NEW."alias"; - END IF; - - SELECT COUNT(*) INTO RowCount - FROM "dns"."cname" - WHERE "dns"."cname"."alias" = NEW."alias"; - IF (RowCount > 0) THEN - RAISE EXCEPTION 'Alias name (%) already exists as a CNAME',NEW."alias"; - END IF; - - -- Autopopulate address - NEW."address" := dns.dns_autopopulate_address(NEW."hostname",NEW."zone"); - - RETURN NEW; - END; -$$; - - -ALTER FUNCTION dns.srv_insert() OWNER TO starrs_admin; - --- --- Name: FUNCTION srv_insert(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION srv_insert() IS 'Check if the alias already exists as an address record'; - - --- --- Name: srv_update(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION srv_update() RETURNS trigger - LANGUAGE plpgsql - AS $$ - DECLARE - RowCount INTEGER; - BEGIN - -- Check if alias name already exists - IF NEW."alias" != OLD."alias" THEN - SELECT COUNT(*) INTO RowCount - FROM "dns"."a" - WHERE "dns"."a"."hostname" = NEW."alias"; - IF (RowCount > 0) THEN - RAISE EXCEPTION 'Alias name (%) already exists',NEW."alias"; - END IF; - - SELECT COUNT(*) INTO RowCount - FROM "dns"."cname" - WHERE "dns"."cname"."alias" = NEW."alias"; - IF (RowCount > 0) THEN - RAISE EXCEPTION 'Alias name (%) already exists as a CNAME',NEW."alias"; - END IF; - END IF; - - -- Autopopulate address - IF NEW."address" != OLD."address" THEN - NEW."address" := dns.dns_autopopulate_address(NEW."hostname",NEW."zone"); - END IF; - - RETURN NEW; - END; -$$; - - -ALTER FUNCTION dns.srv_update() OWNER TO starrs_admin; - --- --- Name: FUNCTION srv_update(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION srv_update() IS 'Check if the new alias already exists as an address record'; - - --- --- Name: txt_insert(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION txt_insert() RETURNS trigger - LANGUAGE plpgsql - AS $$ - BEGIN - NEW."address" := dns.dns_autopopulate_address(NEW."hostname",NEW."zone"); - RETURN NEW; - END; -$$; - - -ALTER FUNCTION dns.txt_insert() OWNER TO starrs_admin; - --- --- Name: FUNCTION txt_insert(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION txt_insert() IS 'Create new TXT record'; - - --- --- Name: txt_query_delete(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION txt_query_delete() RETURNS trigger - LANGUAGE plpgsql - AS $_$ - DECLARE - ReturnCode TEXT; -- Return code from the nsupdate function - DnsKeyName TEXT; -- The DNS keyname to sign with - DnsKey TEXT; -- The DNS key to sign with - DnsServer INET; -- The nameserver to send the update to - DnsRecord TEXT; -- The formatted string that is the record - BEGIN - IF (SELECT "ddns" FROM "dns"."zones" WHERE "dns"."zones"."zone" = OLD."zone") IS FALSE THEN - RETURN OLD; - END IF; - - -- If this is a forward zone: - IF (SELECT "forward" FROM "dns"."zones" WHERE "zone" = OLD."zone") IS TRUE THEN - SELECT "dns"."keys"."keyname","dns"."keys"."key",api.resolve("dns"."soa"."nameserver") - INTO DnsKeyName, DnsKey, DnsServer - FROM "dns"."zones" - JOIN "dns"."keys" ON "dns"."keys"."keyname" = "dns"."zones"."keyname" - JOIN "dns"."soa" ON "dns"."soa"."zone" = "dns"."zones"."zone" - WHERE "dns"."zones"."zone" = OLD."zone"; - -- If this is a reverse zone: - ELSE - SELECT "dns"."keys"."keyname","dns"."keys"."key",api.resolve("dns"."soa"."nameserver") - INTO DnsKeyName, DnsKey, DnsServer - FROM "dns"."zones" - JOIN "dns"."keys" ON "dns"."keys"."keyname" = "dns"."zones"."keyname" - JOIN "dns"."soa" ON "dns"."soa"."zone" = "dns"."zones"."zone" - WHERE "dns"."ns"."zone" = (SELECT "ip"."subnets"."zone" FROM "ip"."subnets" WHERE api.get_reverse_domain("subnet") = OLD."zone"); - END IF; - - -- Just make sure no-one is forcing a bogus type - IF OLD."type" !~* '^TXT$' THEN - RAISE EXCEPTION 'Trying to delete a non-TXT record in a TXT table!'; - END IF; - - -- Create and fire off the update - -- For zone TXT records - IF OLD."hostname" IS NULL THEN - DnsRecord := OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' "'||OLD."text"||'"'; - ELSE - DnsRecord := OLD."hostname"||'.'||OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' "'||OLD."text"||'"'; - END IF; - ReturnCode := api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - - -- Check for result - IF ReturnCode != '0' THEN - RAISE EXCEPTION 'DNS Error: % when performing TXT-DELETE %',ReturnCode,DnsRecord; - END IF; - - -- Done! - RETURN OLD; - END; -$_$; - - -ALTER FUNCTION dns.txt_query_delete() OWNER TO starrs_admin; - --- --- Name: FUNCTION txt_query_delete(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION txt_query_delete() IS 'Delete an old TXT record from the server'; - - --- --- Name: txt_query_insert(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION txt_query_insert() RETURNS trigger - LANGUAGE plpgsql - AS $_$ - DECLARE - ReturnCode TEXT; -- Return code from the nsupdate function - DnsKeyName TEXT; -- The DNS keyname to sign with - DnsKey TEXT; -- The DNS key to sign with - DnsServer INET; -- The nameserver to send the update to - DnsRecord TEXT; -- The formatted string that is the record - BEGIN - IF (SELECT "ddns" FROM "dns"."zones" WHERE "dns"."zones"."zone" = NEW."zone") IS FALSE THEN - RETURN NEW; - END IF; - - -- If this is a forward zone: - IF (SELECT "forward" FROM "dns"."zones" WHERE "zone" = NEW."zone") IS TRUE THEN - SELECT "dns"."keys"."keyname","dns"."keys"."key",api.resolve("dns"."soa"."nameserver") - INTO DnsKeyName, DnsKey, DnsServer - FROM "dns"."zones" - JOIN "dns"."keys" ON "dns"."keys"."keyname" = "dns"."zones"."keyname" - JOIN "dns"."soa" ON "dns"."soa"."zone" = "dns"."zones"."zone" - WHERE "dns"."zones"."zone" = NEW."zone"; - -- If this is a reverse zone: - ELSE - SELECT "dns"."keys"."keyname","dns"."keys"."key",api.resolve("dns"."soa"."nameserver") - INTO DnsKeyName, DnsKey, DnsServer - FROM "dns"."zones" - JOIN "dns"."keys" ON "dns"."keys"."keyname" = "dns"."zones"."keyname" - JOIN "dns"."soa" ON "dns"."soa"."zone" = "dns"."zones"."zone" - WHERE "dns"."ns"."zone" = (SELECT "ip"."subnets"."zone" FROM "ip"."subnets" WHERE api.get_reverse_domain("subnet") = NEW."zone"); - END IF; - - -- Just make sure no-one is forcing a bogus type - IF NEW."type" !~* '^TXT$' THEN - RAISE EXCEPTION 'Trying to create a non-TXT record in a TXT table!'; - END IF; - - -- Create and fire off the update - -- For zone TXT records - IF NEW."hostname" IS NULL THEN - DnsRecord := NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' "'||NEW."text"||'"'; - ELSE - DnsRecord := NEW."hostname"||'.'||NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' "'||NEW."text"||'"'; - END IF; - ReturnCode := api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - - -- Check for result - IF ReturnCode != '0' THEN - RAISE EXCEPTION 'DNS Error: % when performing TXT-INSERT %',ReturnCode,DnsRecord; - END IF; - - -- Done! - RETURN NEW; - END; -$_$; - - -ALTER FUNCTION dns.txt_query_insert() OWNER TO starrs_admin; - --- --- Name: FUNCTION txt_query_insert(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION txt_query_insert() IS 'Update the nameserver with a new TXT record'; - - --- --- Name: txt_query_update(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION txt_query_update() RETURNS trigger - LANGUAGE plpgsql - AS $_$ - DECLARE - ReturnCode TEXT; -- Return code from the nsupdate function - DnsKeyName TEXT; -- The DNS keyname to sign with - DnsKey TEXT; -- The DNS key to sign with - DnsServer INET; -- The nameserver to send the update to - DnsRecord TEXT; -- The formatted string that is the record - BEGIN - -- If this is a forward zone: - IF (SELECT "forward" FROM "dns"."zones" WHERE "zone" = NEW."zone") IS TRUE THEN - SELECT "dns"."keys"."keyname","dns"."keys"."key",api.resolve("dns"."soa"."nameserver") - INTO DnsKeyName, DnsKey, DnsServer - FROM "dns"."zones" - JOIN "dns"."keys" ON "dns"."keys"."keyname" = "dns"."zones"."keyname" - JOIN "dns"."soa" ON "dns"."soa"."zone" = "dns"."zones"."zone" - WHERE "dns"."zones"."zone" = NEW."zone"; - -- If this is a reverse zone: - ELSE - SELECT "dns"."keys"."keyname","dns"."keys"."key",api.resolve("dns"."soa"."nameserver") - INTO DnsKeyName, DnsKey, DnsServer - FROM "dns"."zones" - JOIN "dns"."keys" ON "dns"."keys"."keyname" = "dns"."zones"."keyname" - JOIN "dns"."soa" ON "dns"."soa"."zone" = "dns"."zones"."zone" - WHERE "dns"."ns"."zone" = (SELECT "ip"."subnets"."zone" FROM "ip"."subnets" WHERE api.get_reverse_domain("subnet") = NEW."zone"); - END IF; - - -- Just make sure no-one is forcing a bogus type - IF NEW."type" !~* '^TXT$' THEN - RAISE EXCEPTION 'Trying to update a non-TXT record in a TXT table!'; - END IF; - - IF (SELECT "ddns" FROM "dns"."zones" WHERE "dns"."zones"."zone" = OLD."zone") IS FALSE THEN - RETURN NEW; - END IF; - - -- Delete the record first - IF OLD."hostname" IS NULL THEN - DnsRecord := OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' "'||OLD."text"||'"'; - ELSE - DnsRecord := OLD."hostname"||'.'||OLD."zone"||' '||OLD."ttl"||' '||OLD."type"||' "'||OLD."text"||'"'; - END IF; - ReturnCode := api.nsupdate(OLD."zone",DnsKeyName,DnsKey,DnsServer,'DELETE',DnsRecord); - - -- Check for result - IF ReturnCode != '0' THEN - RAISE EXCEPTION 'DNS Error: % when performing TXT-UPDATE-DELETE %',ReturnCode,DnsRecord; - END IF; - - IF (SELECT "ddns" FROM "dns"."zones" WHERE "dns"."zones"."zone" = NEW."zone") IS FALSE THEN - RETURN NEW; - END IF; - - -- Create and fire off the update - IF NEW."hostname" IS NULL THEN - DnsRecord := NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' "'||NEW."text"||'"'; - ELSE - DnsRecord := NEW."hostname"||'.'||NEW."zone"||' '||NEW."ttl"||' '||NEW."type"||' "'||NEW."text"||'"'; - END IF; - ReturnCode := api.nsupdate(NEW."zone",DnsKeyName,DnsKey,DnsServer,'ADD',DnsRecord); - - -- Check for result - IF ReturnCode != '0' THEN - RAISE EXCEPTION 'DNS Error: % when performing TXT-UPDATE-INSERT %',ReturnCode,DnsRecord; - END IF; - - -- Done! - RETURN NEW; - END; -$_$; - - -ALTER FUNCTION dns.txt_query_update() OWNER TO starrs_admin; - --- --- Name: FUNCTION txt_query_update(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION txt_query_update() IS 'Update the nameserver with a new TXT record'; - - --- --- Name: txt_update(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION txt_update() RETURNS trigger - LANGUAGE plpgsql - AS $$ - BEGIN - IF NEW."address" != OLD."address" THEN - NEW."address" := dns.dns_autopopulate_address(NEW."hostname",NEW."zone"); - END IF; - RETURN NEW; - END; -$$; - - -ALTER FUNCTION dns.txt_update() OWNER TO starrs_admin; - --- --- Name: FUNCTION txt_update(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION txt_update() IS 'Modify a TXT record'; - - --- --- Name: zone_a_delete(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION zone_a_delete() RETURNS trigger - LANGUAGE plpgsql - AS $$ - BEGIN - IF family(OLD."address") = 4 THEN - OLD."type" = 'A'; - ELSE - OLD."type" = 'AAAA'; - END IF; - RETURN OLD; - END; -$$; - - -ALTER FUNCTION dns.zone_a_delete() OWNER TO starrs_admin; - --- --- Name: FUNCTION zone_a_delete(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION zone_a_delete() IS 'Auto-fill the type based on the address family.'; - - --- --- Name: zone_a_insert(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION zone_a_insert() RETURNS trigger - LANGUAGE plpgsql - AS $$ - BEGIN - IF family(NEW."address") = 4 THEN - NEW."type" = 'A'; - ELSE - NEW."type" = 'AAAA'; - END IF; - RETURN NEW; - END; -$$; - - -ALTER FUNCTION dns.zone_a_insert() OWNER TO starrs_admin; - --- --- Name: FUNCTION zone_a_insert(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION zone_a_insert() IS 'Auto-fill the type based on the address family.'; - - --- --- Name: zone_a_update(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION zone_a_update() RETURNS trigger - LANGUAGE plpgsql - AS $$ - BEGIN - IF family(NEW."address") = 4 THEN - NEW."type" = 'A'; - ELSE - NEW."type" = 'AAAA'; - END IF; - RETURN NEW; - END; -$$; - - -ALTER FUNCTION dns.zone_a_update() OWNER TO starrs_admin; - --- --- Name: FUNCTION zone_a_update(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION zone_a_update() IS 'Auto-fill the type based on the address family.'; - - --- --- Name: zone_txt_insert(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION zone_txt_insert() RETURNS trigger - LANGUAGE plpgsql - AS $$ - DECLARE - RowCount INTEGER; - - BEGIN - IF NEW."hostname" IS NOT NULL THEN - -- Check if hostname name already exists as an A - SELECT COUNT(*) INTO RowCount - FROM "dns"."a" - WHERE "dns"."a"."hostname" = NEW."hostname"; - IF (RowCount > 0) THEN - RAISE EXCEPTION 'Hostname (%) already exists',NEW."hostname"; - END IF; - - -- Check if hostname name already exists as an SRV - SELECT COUNT(*) INTO RowCount - FROM "dns"."srv" - WHERE "dns"."srv"."alias" = NEW."hostname"; - IF (RowCount > 0) THEN - RAISE EXCEPTION 'hostname (%) already exists as a SRV',NEW."hostname"; - END IF; - - -- Check if hostname name already exists as an CNAME - SELECT COUNT(*) INTO RowCount - FROM "dns"."cname" - WHERE "dns"."cname"."alias" = NEW."hostname"; - IF (RowCount > 0) THEN - RAISE EXCEPTION 'hostname (%) already exists as a CNAME',NEW."hostname"; - END IF; - END IF; - - RETURN NEW; - END; -$$; - - -ALTER FUNCTION dns.zone_txt_insert() OWNER TO starrs_admin; - --- --- Name: FUNCTION zone_txt_insert(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION zone_txt_insert() IS 'Check if the hostname already exists in other tables and insert the zone TXT record'; - - --- --- Name: zone_txt_update(); Type: FUNCTION; Schema: dns; Owner: starrs_admin --- - -CREATE FUNCTION zone_txt_update() RETURNS trigger - LANGUAGE plpgsql - AS $$ - DECLARE - RowCount INTEGER; - - BEGIN - -- Check if hostname name already exists - IF NEW."hostname" != OLD."hostname" THEN - IF NEW."hostname" IS NOT NULL THEN - -- Check if hostname name already exists as an A - SELECT COUNT(*) INTO RowCount - FROM "dns"."a" - WHERE "dns"."a"."hostname" = NEW."hostname"; - IF (RowCount > 0) THEN - RAISE EXCEPTION 'Hostname (%) already exists',NEW."hostname"; - END IF; - - -- Check if hostname name already exists as an SRV - SELECT COUNT(*) INTO RowCount - FROM "dns"."srv" - WHERE "dns"."srv"."alias" = NEW."hostname"; - IF (RowCount > 0) THEN - RAISE EXCEPTION 'hostname (%) already exists as a SRV',NEW."hostname"; - END IF; - - -- Check if hostname name already exists as an CNAME - SELECT COUNT(*) INTO RowCount - FROM "dns"."cname" - WHERE "dns"."cname"."alias" = NEW."hostname"; - IF (RowCount > 0) THEN - RAISE EXCEPTION 'hostname (%) already exists as a CNAME',NEW."hostname"; - END IF; - END IF; - END IF; - - RETURN NEW; - END; -$$; - - -ALTER FUNCTION dns.zone_txt_update() OWNER TO starrs_admin; - --- --- Name: FUNCTION zone_txt_update(); Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON FUNCTION zone_txt_update() IS 'Check if the new hostname already exists in other tables and update the zone TXT record'; - - -SET search_path = ip, pg_catalog; - --- --- Name: addresses_insert(); Type: FUNCTION; Schema: ip; Owner: starrs_admin --- - -CREATE FUNCTION addresses_insert() RETURNS trigger - LANGUAGE plpgsql - AS $$ - DECLARE - RowCount INTEGER; - BEGIN - -- Done - RETURN NEW; - END; -$$; - - -ALTER FUNCTION ip.addresses_insert() OWNER TO starrs_admin; - --- --- Name: FUNCTION addresses_insert(); Type: COMMENT; Schema: ip; Owner: starrs_admin --- - -COMMENT ON FUNCTION addresses_insert() IS 'Activate a new IP address in the application'; - - --- --- Name: ranges_insert(); Type: FUNCTION; Schema: ip; Owner: starrs_admin --- - -CREATE FUNCTION ranges_insert() RETURNS trigger - LANGUAGE plpgsql - AS $$ - DECLARE - LowerBound INET; - UpperBound INET; - query_result RECORD; - RowCount INTEGER; - BEGIN - -- Check for illegal addresses - IF host(NEW."subnet") = host(NEW."first_ip") THEN - RAISE EXCEPTION 'You cannot have a boundry that is the network identifier'; - END IF; - - -- Check address vs subnet - IF NOT NEW."first_ip" << NEW."subnet" OR NOT NEW."last_ip" << NEW."subnet" THEN - RAISE EXCEPTION 'Range addresses must be inside the specified subnet'; - END IF; - - -- Check valid range - IF NEW."first_ip" >= NEW."last_ip" THEN - RAISE EXCEPTION 'First address is larger or equal to last address.'; - END IF; - - -- IPv6 - IF family(NEW."subnet") = 6 THEN - INSERT INTO "ip"."addresses" ("address") (SELECT * FROM "api"."get_range_addresses"(NEW."first_ip", NEW."last_ip") AS "potential" WHERE "potential" NOT IN (SELECT "address" FROM "ip"."addresses" WHERE "ip"."addresses"."address" << NEW."subnet")); - END IF; - - -- Check address existance - SELECT COUNT(*) INTO RowCount - FROM "ip"."addresses" - WHERE "ip"."addresses"."address" = NEW."first_ip"; - IF (RowCount != 1) THEN - RAISE EXCEPTION 'First address (%) not found in address pool.',NEW."first_ip"; - END IF; - - SELECT COUNT(*) INTO RowCount - FROM "ip"."addresses" - WHERE "ip"."addresses"."address" = NEW."last_ip"; - IF (RowCount != 1) THEN - RAISE EXCEPTION 'Last address (%) not found in address pool.',NEW."last_ip"; - END IF; - - -- Define lower boundary for range - -- Loop through all ranges and find what is near the new range - FOR query_result IN SELECT "first_ip","last_ip" FROM "ip"."ranges" WHERE "subnet" = NEW."subnet" ORDER BY "last_ip" LOOP - IF NEW."first_ip" >= query_result.first_ip AND NEW."first_ip" <= query_result.last_ip THEN - RAISE EXCEPTION 'First address out of bounds.'; - ELSIF NEW."first_ip" > query_result.last_ip THEN - LowerBound := query_result.last_ip; - END IF; - IF NEW."last_ip" >= query_result.first_ip AND NEW."last_ip" <= query_result.last_ip THEN - RAISE EXCEPTION 'Last address is out of bounds'; - END IF; - END LOOP; - - -- Define upper boundry for range - SELECT "first_ip" INTO UpperBound - FROM "ip"."ranges" - WHERE "first_ip" >= LowerBound - ORDER BY "first_ip" LIMIT 1; - - -- Check for range spanning - IF NEW."last_ip" >= UpperBound THEN - RAISE EXCEPTION 'Last address is out of bounds'; - END IF; - - -- Done - RETURN NEW; - END; -$$; - - -ALTER FUNCTION ip.ranges_insert() OWNER TO starrs_admin; - --- --- Name: FUNCTION ranges_insert(); Type: COMMENT; Schema: ip; Owner: starrs_admin --- - -COMMENT ON FUNCTION ranges_insert() IS 'Insert a new range of addresses for use'; - - --- --- Name: ranges_update(); Type: FUNCTION; Schema: ip; Owner: starrs_admin --- - -CREATE FUNCTION ranges_update() RETURNS trigger - LANGUAGE plpgsql - AS $$ - DECLARE - LowerBound INET; - UpperBound INET; - query_result RECORD; - RowCount INTEGER; - BEGIN - IF NEW."first_ip" != OLD."first_ip" OR NEW."last_ip" != OLD."last_ip" THEN - -- Check for illegal addresses - IF host(NEW."subnet") = host(NEW."first_ip") THEN - RAISE EXCEPTION 'You cannot have a boundry that is the network identifier'; - END IF; - - -- Check address vs subnet - IF NOT NEW."first_ip" << NEW."subnet" OR NOT NEW."last_ip" << NEW."subnet" THEN - RAISE EXCEPTION 'Range addresses must be inside the specified subnet'; - END IF; - - -- Check valid range - IF NEW."first_ip" >= NEW."last_ip" THEN - RAISE EXCEPTION 'First address is larger or equal to last address.'; - END IF; - - -- Check address existance - SELECT COUNT(*) INTO RowCount - FROM "ip"."addresses" - WHERE "ip"."addresses"."address" = NEW."first_ip"; - IF (RowCount != 1) THEN - RAISE EXCEPTION 'First address (%) not found in address pool.',NEW."first_ip"; - END IF; - - SELECT COUNT(*) INTO RowCount - FROM "ip"."addresses" - WHERE "ip"."addresses"."address" = NEW."last_ip"; - IF (RowCount != 1) THEN - RAISE EXCEPTION 'Last address (%) not found in address pool.',NEW."last_ip"; - END IF; - - -- Define lower boundary for range - -- Loop through all ranges and find what is near the new range - FOR query_result IN SELECT "first_ip","last_ip" FROM "ip"."ranges" WHERE "subnet" = NEW."subnet" AND "first_ip" != OLD."first_ip" ORDER BY "last_ip" LOOP - -- Check if the new first_ip is contained within the next lower range - IF NEW."first_ip" >= query_result.first_ip AND NEW."first_ip" <= query_result.last_ip THEN - RAISE EXCEPTION 'First address out of bounds.'; - - --Check if the new last_ip is contained with the next lower range - ELSIF NEW."last_ip" >= query_result.first_ip AND NEW."last_ip" <= query_result.last_ip THEN - RAISE EXCEPTION 'Last address LOLOLOL is out of bounds'; - ELSIF NEW."first_ip" > query_result.last_ip THEN - LowerBound := query_result.last_ip; - END IF; - - END LOOP; - - -- Define upper boundry for range - SELECT "first_ip" INTO UpperBound - FROM "ip"."ranges" - WHERE "first_ip" > LowerBound - AND "name" != NEW."name" - ORDER BY "first_ip" DESC LIMIT 1; - - -- Check for range spanning - IF NEW."last_ip" >= UpperBound THEN - RAISE EXCEPTION 'Last address HAHAH is out of bounds'; - END IF; - END IF; - -- Done - RETURN NEW; - END; -$$; - - -ALTER FUNCTION ip.ranges_update() OWNER TO starrs_admin; - --- --- Name: FUNCTION ranges_update(); Type: COMMENT; Schema: ip; Owner: starrs_admin --- - -COMMENT ON FUNCTION ranges_update() IS 'Alter a range of addresses for use'; - - --- --- Name: subnets_delete(); Type: FUNCTION; Schema: ip; Owner: starrs_admin --- - -CREATE FUNCTION subnets_delete() RETURNS trigger - LANGUAGE plpgsql - AS $$ - DECLARE - RowCount INTEGER; - BEGIN - -- Check for inuse addresses - SELECT COUNT(*) INTO RowCount - FROM "ip"."addresses" - WHERE EXISTS ( - SELECT "address" - FROM "systems"."interface_addresses" - WHERE "systems"."interface_addresses"."address" = "ip"."addresses"."address" ) - AND "ip"."addresses"."address" << OLD."subnet"; - IF (RowCount >= 1) THEN - RAISE EXCEPTION 'Inuse addresses found. Aborting delete.'; - END IF; - - -- Delete autogenerated addresses - IF OLD."autogen" = TRUE THEN - DELETE FROM "ip"."addresses" WHERE "address" << OLD."subnet"; - END IF; - - -- Done - RETURN OLD; - END; -$$; - - -ALTER FUNCTION ip.subnets_delete() OWNER TO starrs_admin; - --- --- Name: FUNCTION subnets_delete(); Type: COMMENT; Schema: ip; Owner: starrs_admin --- - -COMMENT ON FUNCTION subnets_delete() IS 'You can only delete a subnet if no addresses from it are inuse.'; - - --- --- Name: subnets_insert(); Type: FUNCTION; Schema: ip; Owner: starrs_admin --- - -CREATE FUNCTION subnets_insert() RETURNS trigger - LANGUAGE plpgsql - AS $$ - DECLARE - RowCount INTEGER; - SubnetAddresses RECORD; - BEGIN - -- Check for larger subnets - SELECT COUNT(*) INTO RowCount - FROM "ip"."subnets" - WHERE NEW."subnet" << "ip"."subnets"."subnet"; - IF (RowCount > 1) THEN - RAISE EXCEPTION 'A larger existing subnet was detected. Nested subnets are not supported.'; - END IF; - - -- Check for smaller subnets - SELECT COUNT(*) INTO RowCount - FROM "ip"."subnets" - WHERE NEW."subnet" >> "ip"."subnets"."subnet"; - IF (RowCount > 0) THEN - RAISE EXCEPTION 'A smaller existing subnet was detected. Nested subnets are not supported.'; - END IF; - - -- Check for existing addresses - SELECT COUNT(*) INTO RowCount - FROM "ip"."addresses" - WHERE "ip"."addresses"."address" << NEW."subnet"; - IF RowCount >= 1 THEN - RAISE EXCEPTION 'Existing addresses detected for your subnet. Modify the existing subnet.'; - END IF; - - -- Autogenerate addresses & firewall default - IF NEW."autogen" IS TRUE THEN - FOR SubnetAddresses IN SELECT api.get_subnet_addresses(NEW."subnet") LOOP - INSERT INTO "ip"."addresses" ("address") VALUES (SubnetAddresses.get_subnet_addresses); - END LOOP; - END IF; - - -- Done - RETURN NEW; - END; -$$; - - -ALTER FUNCTION ip.subnets_insert() OWNER TO starrs_admin; - --- --- Name: FUNCTION subnets_insert(); Type: COMMENT; Schema: ip; Owner: starrs_admin --- - -COMMENT ON FUNCTION subnets_insert() IS 'Create a subnet'; - - --- --- Name: subnets_update(); Type: FUNCTION; Schema: ip; Owner: starrs_admin --- - -CREATE FUNCTION subnets_update() RETURNS trigger - LANGUAGE plpgsql - AS $$ - DECLARE - RowCount INTEGER; - SubnetAddresses RECORD; - BEGIN - IF NEW."subnet" != OLD."subnet" THEN - -- Check for larger subnets - SELECT COUNT(*) INTO RowCount - FROM "ip"."subnets" - WHERE NEW."subnet" << "ip"."subnets"."subnet"; - IF (RowCount > 0) THEN - RAISE EXCEPTION 'A larger existing subnet was detected. Nested subnets are not supported.'; - END IF; - - -- Check for smaller subnets - SELECT COUNT(*) INTO RowCount - FROM "ip"."subnets" - WHERE NEW."subnet" >> "ip"."subnets"."subnet" - AND OLD."subnet" <> "ip"."subnets"."subnet"; - IF (RowCount > 0) THEN - RAISE EXCEPTION 'A smaller existing subnet was detected. Nested subnets are not supported.'; - END IF; - - -- Check for existing addresses - SELECT COUNT(*) INTO RowCount - FROM "ip"."addresses" - WHERE "ip"."addresses"."address" << NEW."subnet"; - IF RowCount >= 1 THEN - RAISE EXCEPTION 'Existing addresses detected for your subnet. Modify the existing subnet.'; - END IF; - END IF; - - -- Autogenerate addresses - IF NEW."autogen" != OLD."autogen" THEN - IF NEW."autogen" IS TRUE THEN - DELETE FROM "ip"."addresses" WHERE "ip"."addresses"."address" << OLD."subnet"; - FOR SubnetAddresses IN SELECT api.get_subnet_addresses(NEW."subnet") LOOP - INSERT INTO "ip"."addresses" ("address") VALUES (SubnetAddresses.get_subnet_addresses); - END LOOP; - END IF; - END IF; - - -- Done - RETURN NEW; - END; -$$; - - -ALTER FUNCTION ip.subnets_update() OWNER TO starrs_admin; - --- --- Name: FUNCTION subnets_update(); Type: COMMENT; Schema: ip; Owner: starrs_admin --- - -COMMENT ON FUNCTION subnets_update() IS 'Modify an existing new subnet'; - - -SET search_path = network, pg_catalog; - --- --- Name: switchport_states_update(); Type: FUNCTION; Schema: network; Owner: starrs_admin --- - -CREATE FUNCTION switchport_states_update() RETURNS trigger - LANGUAGE plpgsql - AS $$ - BEGIN - IF NEW."admin_state" != OLD."admin_state" THEN - PERFORM api.modify_network_switchport_admin_state(api.get_system_primary_address(NEW."system_name"),NEW."port_name",(SELECT "snmp_rw_community" FROM "network"."switchview" WHERE "system_name" = NEW."system_name"),NEW."admin_state"); - END IF; - RETURN NEW; - END; -$$; - - -ALTER FUNCTION network.switchport_states_update() OWNER TO starrs_admin; - --- --- Name: switchports_insert(); Type: FUNCTION; Schema: network; Owner: starrs_admin --- - -CREATE FUNCTION switchports_insert() RETURNS trigger - LANGUAGE plpgsql - AS $$ - DECLARE - DeviceType TEXT; - BEGIN - -- Check for system types - SELECT "type" INTO DeviceType - FROM "systems"."systems" - WHERE "systems"."systems"."system_name" = NEW."system_name"; - IF DeviceType !~* 'Router|Switch|Hub|Wireless Access Point' THEN - RAISE EXCEPTION 'Cannot create a switchport on non-network device type (%)',DeviceType; - END IF; - RETURN NEW; - END; -$$; - - -ALTER FUNCTION network.switchports_insert() OWNER TO starrs_admin; - --- --- Name: FUNCTION switchports_insert(); Type: COMMENT; Schema: network; Owner: starrs_admin --- - -COMMENT ON FUNCTION switchports_insert() IS 'verifications for network switchports'; - - --- --- Name: switchports_update(); Type: FUNCTION; Schema: network; Owner: starrs_admin --- - -CREATE FUNCTION switchports_update() RETURNS trigger - LANGUAGE plpgsql - AS $$ - DECLARE - DeviceType TEXT; - BEGIN - -- Check for system types - IF NEW."system_name" != OLD."system_name" THEN - SELECT "type" INTO DeviceType - FROM "systems"."systems" - WHERE "systems"."systems"."system_name" = NEW."system_name"; - IF DeviceType !~* 'Router|Switch|Hub|Wireless Access Point' THEN - RAISE EXCEPTION 'Cannot create a switchport on non-network device type %',DeviceType; - END IF; - END IF; - - IF NEW."description" != OLD."description" THEN - PERFORM api.modify_network_switchport_description(api.get_system_primary_address(NEW."system_name"),NEW."port_name",(SELECT "snmp_rw_community" FROM "network"."switchview" WHERE "system_name" = NEW."system_name"),NEW."description"); - END IF; - - RETURN NEW; - END; -$$; - - -ALTER FUNCTION network.switchports_update() OWNER TO starrs_admin; - --- --- Name: FUNCTION switchports_update(); Type: COMMENT; Schema: network; Owner: starrs_admin --- - -COMMENT ON FUNCTION switchports_update() IS 'verifications for network switchports'; - - -SET search_path = systems, pg_catalog; - --- --- Name: interface_addresses_insert(); Type: FUNCTION; Schema: systems; Owner: starrs_admin --- - -CREATE FUNCTION interface_addresses_insert() RETURNS trigger - LANGUAGE plpgsql - AS $$ - DECLARE - RowCount INTEGER; - ConfigFamily INTEGER; - PrimaryName TEXT; - Owner TEXT; - BEGIN - -- Set address family - NEW."family" := family(NEW."address"); - - -- Check if address is within a subnet - SELECT COUNT(*) INTO RowCount - FROM "ip"."subnets" - WHERE NEW."address" << "ip"."subnets"."subnet"; - IF (RowCount < 1) THEN - RAISE EXCEPTION 'IP address (%) must be within a managed subnet.',NEW."address"; - END IF; - - -- Check if primary address exists (it shouldnt) - SELECT COUNT(*) INTO RowCount - FROM "systems"."interface_addresses" - WHERE "systems"."interface_addresses"."isprimary" = TRUE - AND "systems"."interface_addresses"."family" = NEW."family" - AND "systems"."interface_addresses"."mac" = NEW."mac"; - IF NEW."isprimary" IS TRUE AND RowCount > 0 THEN - -- There is a primary address already registered and this was supposed to be one. - RAISE EXCEPTION 'Primary address for this interface and family already exists'; - ELSIF NEW."isprimary" IS FALSE AND RowCount = 0 THEN - -- There is no primary and this is set to not be one. - RAISE EXCEPTION 'No primary address exists for this interface (%) and family (%).',NEW."mac",NEW."family"; - END IF; - - -- Check for one DHCPable address per MAC - IF NEW."config" !~* 'static' THEN - SELECT COUNT(*) INTO RowCount - FROM "systems"."interface_addresses" - WHERE "systems"."interface_addresses"."family" = NEW."family" - AND "systems"."interface_addresses"."config" ~* 'dhcp' - AND "systems"."interface_addresses"."mac" = NEW."mac"; - IF (RowCount > 0) THEN - RAISE EXCEPTION 'Only one DHCP/Autoconfig-able address per MAC (%) is allowed',NEW."mac"; - END IF; - END IF; - - -- Check address family against config type - IF NEW."config" !~* 'static' THEN - SELECT "family" INTO ConfigFamily - FROM "dhcp"."config_types" - WHERE "dhcp"."config_types"."config" = NEW."config"; - IF NEW."family" != ConfigFamily THEN - RAISE EXCEPTION 'Invalid configuration type selected (%) for your address family (%)',NEW."config",NEW."family"; - END IF; - END IF; - - -- IPv6 Autoconfiguration - IF NEW."family" = 6 AND NEW."config" ~* 'autoconf|static' THEN - SELECT "systems"."systems"."owner" INTO Owner - FROM "systems"."interfaces" - JOIN "systems"."systems" ON - "systems"."systems"."system_name" = "systems"."interfaces"."system_name" - WHERE "systems"."interfaces"."mac" = NEW."mac"; - - SELECT COUNT(*) INTO RowCount - FROM "ip"."addresses" - WHERE "ip"."addresses"."address" = NEW."address"; - IF (RowCount = 0) THEN - INSERT INTO "ip"."addresses" ("address","owner") VALUES (NEW."address",Owner); - END IF; - - END IF; - - RETURN NEW; - END; -$$; - - -ALTER FUNCTION systems.interface_addresses_insert() OWNER TO starrs_admin; - --- --- Name: FUNCTION interface_addresses_insert(); Type: COMMENT; Schema: systems; Owner: starrs_admin --- - -COMMENT ON FUNCTION interface_addresses_insert() IS 'Create a new address based on a very complex ruleset'; - - --- --- Name: interface_addresses_update(); Type: FUNCTION; Schema: systems; Owner: starrs_admin --- - -CREATE FUNCTION interface_addresses_update() RETURNS trigger - LANGUAGE plpgsql - AS $_$ - DECLARE - RowCount INTEGER; - ConfigFamily INTEGER; - PrimaryName TEXT; - Owner TEXT; - BEGIN - IF NEW."address" != OLD."address" THEN - -- Set family - NEW."family" := family(NEW."address"); - - -- Check if IP is within our controlled subnets - SELECT COUNT(*) INTO RowCount - FROM "ip"."subnets" - WHERE NEW."address" << "ip"."subnets"."subnet"; - IF (RowCount < 1) THEN - RAISE EXCEPTION 'IP address (%) must be within a managed subnet.',NEW."address"; - END IF; - END IF; - - -- Check if primary for the family already exists. It shouldnt. - IF NEW."isprimary" != OLD."isprimary" THEN - SELECT COUNT(*) INTO RowCount - FROM "systems"."interface_addresses" - WHERE "systems"."interface_addresses"."isprimary" = TRUE - AND "systems"."interface_addresses"."family" = NEW."family" - AND "systems"."interface_addresses"."mac" = NEW."mac"; - IF NEW."isprimary" IS TRUE AND RowCount > 0 THEN - -- There is a primary address already registered and this was supposed to be one. - RAISE EXCEPTION 'Primary address for this interface and family already exists'; - ELSIF NEW."isprimary" IS FALSE AND RowCount = 0 THEN - -- There is no primary and this is set to not be one. - RAISE EXCEPTION 'No primary address exists for this interface and family and this will not be one.'; - END IF; - END IF; - - -- Check for only one DHCPable address per MAC address - IF NEW."config" != OLD."config" THEN - IF NEW."config" ~* '^dhcp$' THEN - SELECT COUNT(*) INTO RowCount - FROM "systems"."interface_addresses" - WHERE "systems"."interface_addresses"."family" = NEW."family" - AND "systems"."interface_addresses"."config" ~* 'dhcp' - AND "systems"."interface_addresses"."mac" = NEW."mac"; - IF (RowCount > 0) THEN - RAISE EXCEPTION 'Only one DHCP/Autoconfig-able address per MAC (%) is allowed',NEW."mac"; - END IF; - END IF; - - -- Check address family against config type - IF NEW."config" !~* 'static' THEN - SELECT "family" INTO ConfigFamily - FROM "dhcp"."config_types" - WHERE "dhcp"."config_types"."config" = NEW."config"; - IF NEW."family" != ConfigFamily THEN - RAISE EXCEPTION 'Invalid configuration type selected (%) for your address family (%)',NEW."config",NEW."family"; - END IF; - END IF; - - -- IPv6 Autoconfiguration - IF NEW."family" = 6 AND NEW."config" ~* 'autoconf' THEN - SELECT COUNT(*) INTO RowCount - FROM "ip"."addresses" - WHERE "ip"."addresses"."address" = NEW."address"; - IF (RowCount > 0) THEN - RAISE EXCEPTION 'Existing address (%) detected. Cannot continue.',NEW."address"; - END IF; - - SELECT "systems"."systems"."owner" INTO Owner - FROM "systems"."interfaces" - JOIN "systems"."systems" ON - "systems"."systems"."system_name" = "systems"."interfaces"."system_name" - WHERE "systems"."interfaces"."mac" = NEW."mac"; - - INSERT INTO "ip"."addresses" ("address","owner") VALUES (NEW."address",Owner); - END IF; - - -- Remove old autoconf addresses - IF OLD."config" ~* 'autoconf' THEN - DELETE FROM "ip"."addresses" WHERE "address" = OLD."address"; - END IF; - END IF; - - -- Check for IPv6 secondary name - /* - IF NEW."family" = 6 AND NEW."isprimary" = FALSE THEN - SELECT "name" INTO PrimaryName - FROM "systems"."interface_addresses" - WHERE "systems"."interface_addresses"."mac" = NEW."mac" - AND "systems"."interface_addresses"."isprimary" = TRUE; - IF NEW."name" != PrimaryName THEN - RAISE EXCEPTION 'IPv6 secondaries must have the same interface name (%) as the primary (%)',NEW."name",PrimaryName; - END IF; - END IF; - */ - RETURN NEW; - END; -$_$; - - -ALTER FUNCTION systems.interface_addresses_update() OWNER TO starrs_admin; - --- --- Name: FUNCTION interface_addresses_update(); Type: COMMENT; Schema: systems; Owner: starrs_admin --- - -COMMENT ON FUNCTION interface_addresses_update() IS 'Modify an existing address based on a very complex ruleset'; - - -SET search_path = dns, pg_catalog; - --- --- Name: types; Type: TABLE; Schema: dns; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE types ( - type text NOT NULL, - comment text, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE dns.types OWNER TO starrs_admin; - --- --- Name: TABLE types; Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON TABLE types IS 'All DNS record types'; - - -SET search_path = ip, pg_catalog; - --- --- Name: addresses; Type: TABLE; Schema: ip; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE addresses ( - address inet NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL, - owner text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE ip.addresses OWNER TO starrs_admin; - --- --- Name: TABLE addresses; Type: COMMENT; Schema: ip; Owner: starrs_admin --- - -COMMENT ON TABLE addresses IS 'Master list of all controlled addresses in the application'; - - --- --- Name: range_uses; Type: TABLE; Schema: ip; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE range_uses ( - use character varying(4) NOT NULL, - comment text, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE ip.range_uses OWNER TO starrs_admin; - --- --- Name: TABLE range_uses; Type: COMMENT; Schema: ip; Owner: starrs_admin --- - -COMMENT ON TABLE range_uses IS 'Ranges are intended for a specific purpose.'; - - -SET search_path = management, pg_catalog; - --- --- Name: log_master; Type: TABLE; Schema: management; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE log_master ( - "timestamp" timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - "user" text NOT NULL, - message text, - source text NOT NULL, - severity text NOT NULL -); - - -ALTER TABLE management.log_master OWNER TO starrs_admin; - --- --- Name: TABLE log_master; Type: COMMENT; Schema: management; Owner: starrs_admin --- - -COMMENT ON TABLE log_master IS 'Record every single transaction that occurs in this application.'; - - --- --- Name: output_id_seq; Type: SEQUENCE; Schema: management; Owner: starrs_admin --- - -CREATE SEQUENCE output_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE management.output_id_seq OWNER TO starrs_admin; - --- --- Name: SEQUENCE output_id_seq; Type: COMMENT; Schema: management; Owner: starrs_admin --- - -COMMENT ON SEQUENCE output_id_seq IS 'Identifier for all output results'; - - --- --- Name: output; Type: TABLE; Schema: management; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE output ( - output_id integer DEFAULT nextval('output_id_seq'::regclass) NOT NULL, - value text, - file text, - "timestamp" timestamp without time zone NOT NULL -); - - -ALTER TABLE management.output OWNER TO starrs_admin; - --- --- Name: TABLE output; Type: COMMENT; Schema: management; Owner: starrs_admin --- - -COMMENT ON TABLE output IS 'Destination of the output functions rather than write a file to disk.'; - - -SET search_path = network, pg_catalog; - --- --- Name: snmp3; Type: TABLE; Schema: network; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE snmp3 ( - system_name text NOT NULL, - "user" text NOT NULL, - auth_encryption text DEFAULT 'md5'::text NOT NULL, - password text NOT NULL, - priv_encryption text DEFAULT 'aes'::text NOT NULL, - priv_password text NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE network.snmp3 OWNER TO starrs_admin; - --- --- Name: TABLE snmp3; Type: COMMENT; Schema: network; Owner: starrs_admin --- - -COMMENT ON TABLE snmp3 IS 'SNMPv3 credentials for network hosts'; - - -SET search_path = systems, pg_catalog; - --- --- Name: os; Type: TABLE; Schema: systems; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE os ( - name text NOT NULL, - family text, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE systems.os OWNER TO starrs_admin; - --- --- Name: TABLE os; Type: COMMENT; Schema: systems; Owner: starrs_admin --- - -COMMENT ON TABLE os IS 'Track what primary operating systems are in use on the network.'; - - --- --- Name: os_family; Type: TABLE; Schema: systems; Owner: starrs_admin; Tablespace: --- - -CREATE TABLE os_family ( - family text NOT NULL, - date_created timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - date_modified timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL, - last_modifier text DEFAULT api.get_current_user() NOT NULL -); - - -ALTER TABLE systems.os_family OWNER TO starrs_admin; - --- --- Name: TABLE os_family; Type: COMMENT; Schema: systems; Owner: starrs_admin --- - -COMMENT ON TABLE os_family IS 'General classification for operating systems.'; - - -SET search_path = dhcp, pg_catalog; - --- --- Data for Name: class_options; Type: TABLE DATA; Schema: dhcp; Owner: starrs_admin --- - -COPY class_options (option, value, date_created, date_modified, last_modifier, class) FROM stdin; -\. - - --- --- Data for Name: classes; Type: TABLE DATA; Schema: dhcp; Owner: starrs_admin --- - -COPY classes (class, comment, date_created, date_modified, last_modifier) FROM stdin; -default Default class 2021-04-30 20:54:34 2021-04-30 20:54:34 root -\. - - --- --- Data for Name: config_types; Type: TABLE DATA; Schema: dhcp; Owner: starrs_admin --- - -COPY config_types (config, comment, last_modifier, date_created, date_modified, family) FROM stdin; -dhcp Regular DHCP root 2021-04-30 20:53:53 2021-04-30 20:53:53 4 -dhcpv6 DHCPv6 root 2021-04-30 20:53:53 2021-04-30 20:53:53 6 -static Manually assigned root 2021-04-30 20:53:53 2021-04-30 20:53:53 0 -autoconf Generated via MAC address root 2021-04-30 20:53:53 2021-04-30 20:53:53 6 -\. - - --- --- Data for Name: global_options; Type: TABLE DATA; Schema: dhcp; Owner: starrs_admin --- - -COPY global_options (option, value, date_created, date_modified, last_modifier) FROM stdin; -\. - - --- --- Data for Name: range_options; Type: TABLE DATA; Schema: dhcp; Owner: starrs_admin --- - -COPY range_options (option, name, date_created, date_modified, last_modifier, value) FROM stdin; -\. - - --- --- Data for Name: subnet_options; Type: TABLE DATA; Schema: dhcp; Owner: starrs_admin --- - -COPY subnet_options (option, value, date_created, date_modified, last_modifier, subnet) FROM stdin; -\. - - -SET search_path = dns, pg_catalog; - --- --- Data for Name: a; Type: TABLE DATA; Schema: dns; Owner: starrs_admin --- - -COPY a (hostname, date_created, date_modified, last_modifier, address, type, ttl, owner, zone, reverse) FROM stdin; -\. - - --- --- Data for Name: cname; Type: TABLE DATA; Schema: dns; Owner: starrs_admin --- - -COPY cname (alias, date_modified, date_created, last_modifier, hostname, address, ttl, owner, type, zone) FROM stdin; -\. - - --- --- Data for Name: keys; Type: TABLE DATA; Schema: dns; Owner: starrs_admin --- - -COPY keys (keyname, key, enctype, date_modified, date_created, last_modifier, comment, owner) FROM stdin; -testkey F00b@r rc4-hmac 2021-04-30 20:54:03 2021-04-30 20:54:03 root Test key root -\. - - --- --- Data for Name: mx; Type: TABLE DATA; Schema: dns; Owner: starrs_admin --- - -COPY mx (preference, date_modified, date_created, last_modifier, hostname, address, ttl, owner, zone, type) FROM stdin; -\. - - --- --- Data for Name: ns; Type: TABLE DATA; Schema: dns; Owner: starrs_admin --- - -COPY ns (zone, ttl, type, nameserver, address, date_modified, date_created, last_modifier) FROM stdin; -\. - - --- --- Data for Name: soa; Type: TABLE DATA; Schema: dns; Owner: starrs_admin --- - -COPY soa (zone, nameserver, ttl, contact, serial, refresh, retry, expire, minimum, date_modified, date_created, last_modifier) FROM stdin; -\. - - --- --- Data for Name: srv; Type: TABLE DATA; Schema: dns; Owner: starrs_admin --- - -COPY srv (alias, priority, weight, port, date_modified, date_created, last_modifier, hostname, address, ttl, owner, type, zone) FROM stdin; -\. - - --- --- Data for Name: txt; Type: TABLE DATA; Schema: dns; Owner: starrs_admin --- - -COPY txt (text, date_modified, date_created, last_modifier, hostname, address, type, ttl, owner, zone) FROM stdin; -\. - - --- --- Data for Name: types; Type: TABLE DATA; Schema: dns; Owner: starrs_admin --- - -COPY types (type, comment, date_created, date_modified, last_modifier) FROM stdin; -A IPv4 address 2021-04-30 20:53:53 2021-04-30 20:53:53 root -AAAA IPv6 address 2021-04-30 20:53:53 2021-04-30 20:53:53 root -NS Nameserver 2021-04-30 20:53:53 2021-04-30 20:53:53 root -MX Mail Exchange 2021-04-30 20:53:53 2021-04-30 20:53:53 root -TXT Text 2021-04-30 20:53:53 2021-04-30 20:53:53 root -CNAME Pointer 2021-04-30 20:53:53 2021-04-30 20:53:53 root -SRV Special service 2021-04-30 20:53:53 2021-04-30 20:53:53 root -\. - - --- --- Data for Name: zone_a; Type: TABLE DATA; Schema: dns; Owner: starrs_admin --- - -COPY zone_a (hostname, zone, type, address, ttl, date_created, date_modified, last_modifier) FROM stdin; -\. - - --- --- Data for Name: zone_txt; Type: TABLE DATA; Schema: dns; Owner: starrs_admin --- - -COPY zone_txt (text, date_modified, date_created, last_modifier, hostname, type, ttl, zone, address) FROM stdin; -\. - - --- --- Data for Name: zones; Type: TABLE DATA; Schema: dns; Owner: starrs_admin --- - -COPY zones (zone, forward, keyname, date_modified, date_created, last_modifier, owner, comment, shared, ddns) FROM stdin; -example.com t testkey 2021-04-30 20:54:03 2021-04-30 20:54:03 root root Root zone t f -49.0.10.in-addr.arpa f testkey 2021-04-30 20:54:03 2021-04-30 20:54:03 root root Reverse zone for subnet 10.0.49.0/24 t f -50.0.10.in-addr.arpa f testkey 2021-04-30 20:54:04 2021-04-30 20:54:04 root root Reverse zone for subnet 10.0.50.0/24 t f -0.0.0.0.0.0.0.0.9.4.0.0.1.0.0.2.ip6.arpa f testkey 2021-04-30 20:54:33 2021-04-30 20:54:33 root root Reverse zone for subnet 2001:49::/64 t f -0.0.0.0.0.0.0.0.0.5.0.0.1.0.0.2.ip6.arpa f testkey 2021-04-30 20:54:33 2021-04-30 20:54:33 root root Reverse zone for subnet 2001:50::/64 t f -\. - - -SET search_path = ip, pg_catalog; - --- --- Data for Name: addresses; Type: TABLE DATA; Schema: ip; Owner: starrs_admin --- - -COPY addresses (address, date_created, date_modified, last_modifier, owner) FROM stdin; -10.0.49.1 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.2 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.3 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.4 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.5 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.6 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.7 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.8 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.9 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.10 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.11 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.12 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.13 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.14 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.15 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.16 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.17 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.18 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.19 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.20 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.21 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.22 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.23 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.24 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.25 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.26 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.27 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.28 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.29 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.30 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.31 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.32 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.33 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.34 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.35 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.36 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.37 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.38 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.39 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.40 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.41 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.42 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.43 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.44 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.45 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.46 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.47 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.48 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.49 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.50 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.51 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.52 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.53 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.54 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.55 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.56 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.57 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.58 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.59 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.60 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.61 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.62 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.63 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.64 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.65 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.66 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.67 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.68 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.69 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.70 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.71 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.72 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.73 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.74 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.75 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.76 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.77 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.78 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.79 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.80 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.81 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.82 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.83 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.84 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.85 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.86 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.87 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.88 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.89 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.90 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.91 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.92 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.93 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.94 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.95 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.96 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.97 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.98 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.99 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.100 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.101 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.102 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.103 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.104 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.105 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.106 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.107 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.108 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.109 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.110 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.111 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.112 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.113 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.114 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.115 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.116 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.117 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.118 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.119 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.120 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.121 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.122 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.123 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.124 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.125 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.126 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.127 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.128 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.129 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.130 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.131 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.132 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.133 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.134 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.135 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.136 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.137 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.138 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.139 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.140 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.141 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.142 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.143 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.144 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.145 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.146 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.147 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.148 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.149 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.150 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.151 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.152 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.153 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.154 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.155 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.156 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.157 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.158 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.159 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.160 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.161 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.162 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.163 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.164 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.165 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.166 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.167 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.168 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.169 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.170 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.171 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.172 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.173 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.174 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.175 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.176 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.177 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.178 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.179 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.180 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.181 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.182 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.183 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.184 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.185 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.186 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.187 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.188 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.189 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.190 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.191 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.192 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.193 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.194 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.195 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.196 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.197 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.198 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.199 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.200 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.201 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.202 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.203 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.204 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.205 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.206 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.207 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.208 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.209 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.210 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.211 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.212 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.213 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.214 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.215 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.216 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.217 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.218 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.219 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.220 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.221 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.222 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.223 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.224 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.225 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.226 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.227 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.228 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.229 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.230 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.231 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.232 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.233 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.234 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.235 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.236 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.237 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.238 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.239 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.240 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.241 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.242 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.243 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.244 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.245 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.246 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.247 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.248 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.249 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.250 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.251 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.252 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.253 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.49.254 2021-04-30 20:54:03 2021-04-30 20:54:03 root root -10.0.50.1 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.2 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.3 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.4 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.5 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.6 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.7 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.8 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.9 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.10 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.11 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.12 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.13 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.14 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.15 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.16 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.17 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.18 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.19 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.20 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.21 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.22 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.23 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.24 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.25 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.26 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.27 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.28 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.29 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.30 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.31 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.32 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.33 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.34 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.35 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.36 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.37 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.38 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.39 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.40 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.41 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.42 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.43 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.44 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.45 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.46 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.47 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.48 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.49 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.50 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.51 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.52 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.53 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.54 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.55 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.56 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.57 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.58 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.59 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.60 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.61 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.62 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.63 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.64 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.65 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.66 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.67 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.68 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.69 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.70 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.71 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.72 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.73 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.74 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.75 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.76 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.77 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.78 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.79 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.80 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.81 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.82 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.83 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.84 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.85 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.86 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.87 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.88 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.89 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.90 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.91 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.92 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.93 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.94 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.95 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.96 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.97 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.98 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.99 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.100 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.101 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.102 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.103 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.104 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.105 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.106 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.107 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.108 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.109 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.110 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.111 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.112 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.113 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.114 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.115 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.116 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.117 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.118 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.119 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.120 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.121 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.122 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.123 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.124 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.125 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.126 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.127 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.128 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.129 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.130 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.131 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.132 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.133 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.134 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.135 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.136 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.137 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.138 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.139 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.140 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.141 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.142 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.143 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.144 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.145 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.146 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.147 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.148 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.149 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.150 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.151 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.152 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.153 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.154 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.155 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.156 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.157 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.158 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.159 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.160 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.161 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.162 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.163 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.164 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.165 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.166 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.167 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.168 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.169 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.170 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.171 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.172 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.173 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.174 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.175 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.176 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.177 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.178 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.179 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.180 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.181 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.182 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.183 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.184 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.185 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.186 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.187 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.188 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.189 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.190 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.191 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.192 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.193 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.194 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.195 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.196 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.197 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.198 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.199 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.200 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.201 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.202 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.203 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.204 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.205 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.206 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.207 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.208 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.209 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.210 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.211 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.212 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.213 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.214 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.215 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.216 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.217 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.218 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.219 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.220 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.221 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.222 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.223 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.224 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.225 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.226 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.227 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.228 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.229 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.230 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.231 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.232 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.233 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.234 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.235 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.236 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.237 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.238 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.239 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.240 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.241 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.242 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.243 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.244 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.245 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.246 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.247 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.248 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.249 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.250 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.251 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.252 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.253 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -10.0.50.254 2021-04-30 20:54:04 2021-04-30 20:54:04 root root -2001:49::1 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::2 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::3 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::4 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::5 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::6 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::7 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::8 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::9 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::10 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::11 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::12 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::13 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::14 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::15 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::16 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::17 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::18 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::19 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::20 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::21 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::22 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::23 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::24 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::25 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::26 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::27 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::28 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::29 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::2a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::2b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::2c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::2d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::2e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::2f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::30 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::31 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::32 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::33 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::34 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::35 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::36 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::37 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::38 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::39 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::3a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::3b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::3c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::3d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::3e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::3f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::40 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::41 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::42 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::43 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::44 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::45 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::46 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::47 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::48 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::49 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::4a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::4b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::4c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::4d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::4e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::4f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::50 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::51 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::52 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::53 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::54 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::55 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::56 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::57 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::58 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::59 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::5a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::5b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::5c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::5d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::5e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::5f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::60 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::61 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::62 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::63 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::64 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::65 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::66 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::67 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::68 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::69 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::6a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::6b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::6c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::6d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::6e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::6f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::70 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::71 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::72 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::73 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::74 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::75 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::76 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::77 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::78 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::79 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::7a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::7b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::7c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::7d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::7e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::7f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::80 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::81 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::82 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::83 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::84 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::85 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::86 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::87 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::88 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::89 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::8a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::8b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::8c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::8d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::8e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::8f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::90 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::91 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::92 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::93 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::94 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::95 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::96 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::97 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::98 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::99 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::9a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::9b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::9c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::9d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::9e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::9f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::a0 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::a1 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::a2 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::a3 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::a4 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::a5 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::a6 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::a7 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::a8 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::a9 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::aa 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::ab 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::ac 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::ad 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::ae 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::af 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::b0 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::b1 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::b2 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::b3 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::b4 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::b5 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::b6 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::b7 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::b8 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::b9 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::ba 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::bb 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::bc 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::bd 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::be 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::bf 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::c0 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::c1 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::c2 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::c3 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::c4 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::c5 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::c6 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::c7 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::c8 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::c9 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::ca 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::cb 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::cc 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::cd 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::ce 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::cf 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::d0 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::d1 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::d2 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::d3 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::d4 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::d5 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::d6 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::d7 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::d8 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::d9 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::da 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::db 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::dc 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::dd 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::de 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::df 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::e0 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::e1 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::e2 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::e3 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::e4 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::e5 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::e6 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::e7 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::e8 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::e9 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::ea 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::eb 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::ec 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::ed 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::ee 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::ef 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::f0 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::f1 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::f2 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::f3 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::f4 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::f5 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::f6 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::f7 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::f8 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::f9 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::fa 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::fb 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::fc 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::fd 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::fe 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::ff 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::100 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::101 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::102 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::103 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::104 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::105 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::106 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::107 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::108 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::109 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::10a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::10b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::10c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::10d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::10e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::10f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::110 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::111 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::112 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::113 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::114 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::115 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::116 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::117 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::118 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::119 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::11a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::11b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::11c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::11d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::11e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::11f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::120 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::121 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::122 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::123 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::124 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::125 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::126 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::127 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::128 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::129 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::12a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::12b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::12c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::12d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::12e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::12f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::130 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::131 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::132 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::133 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::134 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::135 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::136 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::137 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::138 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::139 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::13a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::13b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::13c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::13d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::13e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::13f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::140 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::141 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::142 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::143 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::144 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::145 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::146 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::147 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::148 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::149 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::14a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::14b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::14c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::14d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::14e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::14f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::150 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::151 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::152 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::153 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::154 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::155 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::156 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::157 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::158 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::159 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::15a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::15b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::15c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::15d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::15e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::15f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::160 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::161 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::162 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::163 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::164 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::165 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::166 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::167 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::168 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::169 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::16a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::16b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::16c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::16d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::16e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::16f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::170 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::171 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::172 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::173 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::174 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::175 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::176 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::177 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::178 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::179 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::17a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::17b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::17c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::17d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::17e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::17f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::180 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::181 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::182 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::183 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::184 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::185 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::186 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::187 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::188 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::189 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::18a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::18b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::18c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::18d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::18e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::18f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::190 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::191 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::192 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::193 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::194 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::195 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::196 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::197 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::198 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::199 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::19a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::19b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::19c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::19d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::19e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::19f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1a0 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1a1 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1a2 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1a3 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1a4 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1a5 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1a6 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1a7 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1a8 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1a9 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1aa 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1ab 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1ac 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1ad 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1ae 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1af 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1b0 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1b1 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1b2 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1b3 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1b4 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1b5 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1b6 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1b7 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1b8 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1b9 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1ba 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1bb 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1bc 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1bd 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1be 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1bf 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1c0 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1c1 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1c2 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1c3 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1c4 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1c5 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1c6 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1c7 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1c8 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1c9 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1ca 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1cb 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1cc 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1cd 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1ce 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1cf 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1d0 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1d1 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1d2 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1d3 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1d4 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1d5 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1d6 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1d7 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1d8 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1d9 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1da 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1db 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1dc 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1dd 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1de 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1df 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1e0 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1e1 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1e2 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1e3 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1e4 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1e5 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1e6 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1e7 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1e8 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1e9 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1ea 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1eb 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1ec 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1ed 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1ee 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1ef 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1f0 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1f1 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1f2 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1f3 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1f4 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1f5 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1f6 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1f7 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1f8 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1f9 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1fa 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1fb 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1fc 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1fd 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1fe 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::1ff 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::200 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::201 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::202 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::203 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::204 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::205 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::206 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::207 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::208 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::209 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::20a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::20b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::20c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::20d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::20e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::20f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::210 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::211 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::212 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::213 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::214 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::215 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::216 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::217 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::218 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::219 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::21a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::21b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::21c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::21d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::21e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::21f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::220 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::221 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::222 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::223 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::224 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::225 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::226 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::227 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::228 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::229 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::22a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::22b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::22c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::22d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::22e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::22f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::230 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::231 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::232 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::233 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::234 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::235 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::236 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::237 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::238 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::239 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::23a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::23b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::23c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::23d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::23e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::23f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::240 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::241 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::242 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::243 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::244 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::245 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::246 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::247 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::248 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::249 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::24a 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::24b 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::24c 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::24d 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::24e 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::24f 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::250 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::251 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::252 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::253 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::254 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:49::255 2021-04-30 20:54:34 2021-04-30 20:54:34 root root -2001:50::1 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::2 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::3 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::4 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::5 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::6 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::7 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::8 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::9 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::10 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::11 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::12 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::13 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::14 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::15 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::16 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::17 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::18 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::19 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::20 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::21 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::22 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::23 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::24 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::25 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::26 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::27 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::28 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::29 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::2a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::2b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::2c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::2d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::2e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::2f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::30 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::31 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::32 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::33 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::34 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::35 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::36 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::37 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::38 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::39 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::3a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::3b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::3c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::3d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::3e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::3f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::40 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::41 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::42 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::43 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::44 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::45 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::46 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::47 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::48 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::49 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::4a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::4b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::4c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::4d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::4e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::4f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::50 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::51 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::52 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::53 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::54 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::55 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::56 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::57 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::58 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::59 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::5a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::5b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::5c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::5d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::5e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::5f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::60 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::61 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::62 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::63 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::64 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::65 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::66 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::67 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::68 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::69 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::6a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::6b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::6c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::6d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::6e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::6f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::70 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::71 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::72 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::73 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::74 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::75 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::76 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::77 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::78 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::79 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::7a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::7b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::7c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::7d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::7e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::7f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::80 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::81 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::82 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::83 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::84 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::85 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::86 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::87 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::88 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::89 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::8a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::8b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::8c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::8d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::8e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::8f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::90 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::91 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::92 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::93 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::94 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::95 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::96 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::97 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::98 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::99 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::9a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::9b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::9c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::9d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::9e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::9f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::a0 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::a1 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::a2 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::a3 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::a4 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::a5 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::a6 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::a7 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::a8 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::a9 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::aa 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::ab 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::ac 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::ad 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::ae 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::af 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::b0 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::b1 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::b2 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::b3 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::b4 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::b5 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::b6 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::b7 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::b8 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::b9 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::ba 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::bb 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::bc 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::bd 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::be 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::bf 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::c0 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::c1 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::c2 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::c3 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::c4 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::c5 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::c6 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::c7 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::c8 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::c9 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::ca 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::cb 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::cc 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::cd 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::ce 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::cf 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::d0 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::d1 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::d2 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::d3 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::d4 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::d5 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::d6 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::d7 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::d8 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::d9 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::da 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::db 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::dc 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::dd 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::de 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::df 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::e0 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::e1 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::e2 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::e3 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::e4 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::e5 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::e6 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::e7 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::e8 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::e9 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::ea 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::eb 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::ec 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::ed 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::ee 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::ef 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::f0 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::f1 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::f2 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::f3 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::f4 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::f5 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::f6 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::f7 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::f8 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::f9 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::fa 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::fb 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::fc 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::fd 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::fe 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::ff 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::100 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::101 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::102 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::103 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::104 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::105 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::106 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::107 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::108 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::109 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::10a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::10b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::10c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::10d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::10e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::10f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::110 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::111 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::112 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::113 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::114 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::115 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::116 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::117 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::118 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::119 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::11a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::11b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::11c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::11d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::11e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::11f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::120 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::121 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::122 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::123 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::124 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::125 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::126 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::127 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::128 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::129 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::12a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::12b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::12c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::12d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::12e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::12f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::130 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::131 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::132 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::133 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::134 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::135 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::136 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::137 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::138 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::139 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::13a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::13b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::13c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::13d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::13e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::13f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::140 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::141 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::142 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::143 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::144 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::145 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::146 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::147 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::148 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::149 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::14a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::14b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::14c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::14d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::14e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::14f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::150 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::151 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::152 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::153 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::154 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::155 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::156 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::157 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::158 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::159 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::15a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::15b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::15c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::15d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::15e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::15f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::160 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::161 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::162 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::163 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::164 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::165 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::166 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::167 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::168 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::169 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::16a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::16b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::16c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::16d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::16e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::16f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::170 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::171 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::172 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::173 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::174 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::175 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::176 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::177 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::178 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::179 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::17a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::17b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::17c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::17d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::17e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::17f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::180 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::181 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::182 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::183 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::184 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::185 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::186 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::187 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::188 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::189 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::18a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::18b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::18c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::18d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::18e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::18f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::190 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::191 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::192 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::193 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::194 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::195 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::196 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::197 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::198 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::199 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::19a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::19b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::19c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::19d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::19e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::19f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1a0 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1a1 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1a2 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1a3 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1a4 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1a5 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1a6 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1a7 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1a8 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1a9 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1aa 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1ab 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1ac 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1ad 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1ae 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1af 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1b0 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1b1 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1b2 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1b3 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1b4 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1b5 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1b6 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1b7 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1b8 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1b9 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1ba 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1bb 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1bc 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1bd 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1be 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1bf 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1c0 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1c1 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1c2 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1c3 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1c4 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1c5 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1c6 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1c7 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1c8 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1c9 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1ca 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1cb 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1cc 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1cd 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1ce 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1cf 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1d0 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1d1 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1d2 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1d3 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1d4 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1d5 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1d6 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1d7 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1d8 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1d9 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1da 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1db 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1dc 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1dd 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1de 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1df 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1e0 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1e1 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1e2 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1e3 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1e4 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1e5 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1e6 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1e7 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1e8 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1e9 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1ea 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1eb 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1ec 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1ed 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1ee 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1ef 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1f0 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1f1 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1f2 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1f3 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1f4 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1f5 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1f6 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1f7 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1f8 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1f9 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1fa 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1fb 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1fc 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1fd 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1fe 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::1ff 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::200 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::201 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::202 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::203 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::204 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::205 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::206 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::207 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::208 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::209 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::20a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::20b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::20c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::20d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::20e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::20f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::210 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::211 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::212 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::213 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::214 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::215 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::216 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::217 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::218 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::219 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::21a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::21b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::21c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::21d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::21e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::21f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::220 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::221 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::222 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::223 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::224 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::225 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::226 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::227 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::228 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::229 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::22a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::22b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::22c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::22d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::22e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::22f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::230 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::231 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::232 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::233 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::234 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::235 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::236 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::237 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::238 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::239 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::23a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::23b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::23c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::23d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::23e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::23f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::240 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::241 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::242 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::243 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::244 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::245 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::246 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::247 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::248 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::249 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::24a 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::24b 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::24c 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::24d 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::24e 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::24f 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::250 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::251 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::252 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::253 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::254 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -2001:50::255 2021-04-30 20:54:41 2021-04-30 20:54:41 root root -\. - - --- --- Data for Name: range_groups; Type: TABLE DATA; Schema: ip; Owner: starrs_admin --- - -COPY range_groups (range_name, group_name, date_created, date_modified, last_modifier) FROM stdin; -\. - - --- --- Data for Name: range_uses; Type: TABLE DATA; Schema: ip; Owner: starrs_admin --- - -COPY range_uses (use, comment, date_modified, date_created, last_modifier) FROM stdin; -UREG User registration 2021-04-30 20:53:53 2021-04-30 20:53:53 root -ROAM Dynamic (roaming) 2021-04-30 20:53:53 2021-04-30 20:53:53 root -AREG Auto registration 2021-04-30 20:53:53 2021-04-30 20:53:53 root -RESV Reserved 2021-04-30 20:53:53 2021-04-30 20:53:53 root -\. - - --- --- Data for Name: ranges; Type: TABLE DATA; Schema: ip; Owner: starrs_admin --- - -COPY ranges (first_ip, last_ip, comment, use, datacenter, zone, date_modified, date_created, last_modifier, name, subnet, class) FROM stdin; -10.0.49.1 10.0.49.200 Server registrations UREG Rochester Corp 2021-04-30 20:54:34 2021-04-30 20:54:34 root Servers 10.0.49.0/24 default -2001:49::1 2001:49::255 Server registrations UREG Rochester Corp 2021-04-30 20:54:34 2021-04-30 20:54:34 root Servers IPv6 2001:49::/64 default -10.0.50.1 10.0.50.200 User registrations UREG Rochester Corp 2021-04-30 20:54:41 2021-04-30 20:54:41 root Users 10.0.50.0/24 default -2001:50::1 2001:50::255 Server registrations UREG Rochester Corp 2021-04-30 20:54:41 2021-04-30 20:54:41 root Users IPv6 2001:50::/64 default -\. - - --- --- Data for Name: subnets; Type: TABLE DATA; Schema: ip; Owner: starrs_admin --- - -COPY subnets (subnet, comment, autogen, date_created, date_modified, last_modifier, name, owner, zone, dhcp_enable, datacenter, vlan) FROM stdin; -10.0.49.0/24 VLAN49 subnet t 2021-04-30 20:54:03 2021-04-30 20:54:03 root 49v4 root example.com f Rochester 49 -10.0.50.0/24 VLAN50 subnet t 2021-04-30 20:54:04 2021-04-30 20:54:04 root 50v4 root example.com f Rochester 50 -2001:49::/64 VLAN49 IPv6 subnet f 2021-04-30 20:54:33 2021-04-30 20:54:33 root 49v6 root example.com f Rochester 49 -2001:50::/64 VLAN50 IPv6 subnet f 2021-04-30 20:54:33 2021-04-30 20:54:33 root 50v6 root example.com f Rochester 50 -\. - - -SET search_path = libvirt, pg_catalog; - --- --- Data for Name: hosts; Type: TABLE DATA; Schema: libvirt; Owner: starrs_admin --- - -COPY hosts (system_name, uri, password, date_created, date_modified, last_modifier) FROM stdin; -\. - - --- --- Data for Name: platforms; Type: TABLE DATA; Schema: libvirt; Owner: starrs_admin --- - -COPY platforms (platform_name, definition, date_created, date_modified, last_modifier) FROM stdin; -\. - - -SET search_path = management, pg_catalog; - --- --- Data for Name: configuration; Type: TABLE DATA; Schema: management; Owner: starrs_admin --- - -COPY configuration (option, value, date_created, date_modified, last_modifier) FROM stdin; -SYSLOG_FACILITY user 2021-04-30 20:53:53 2021-04-30 20:53:53 root -DEFAULT_CONFIG_TYPE static 2021-04-30 20:53:53 2021-04-30 20:53:53 root -DEFAULT_DATACENTER Rochester 2021-04-30 20:53:53 2021-04-30 20:53:53 root -DEFAULT_GROUP Users 2021-04-30 20:53:53 2021-04-30 20:53:53 root -DEFAULT_INTERFACE_NAME Main Interface 2021-04-30 20:53:53 2021-04-30 20:53:53 root -DEFAULT_LOCAL_ADMIN_GROUP Administrators 2021-04-30 20:53:53 2021-04-30 20:53:53 root -DEFAULT_LOCAL_USER_GROUP Users 2021-04-30 20:53:53 2021-04-30 20:53:53 root -DEFAULT_RENEW_INTERVAL 1 year 2021-04-30 20:54:02 2021-04-30 20:54:02 root -DEFAULT_SYSTEM_PLATFORM Custom 2021-04-30 20:54:02 2021-04-30 20:54:02 root -DEFAULT_SYSTEM_TYPE Server 2021-04-30 20:54:02 2021-04-30 20:54:02 root -DHCPD_DEFAULT_CLASS default 2021-04-30 20:54:03 2021-04-30 20:54:03 root -DNS_DEFAULT_TTL 3600 2021-04-30 20:54:03 2021-04-30 20:54:03 root -DNS_DEFAULT_ZONE example.com 2021-04-30 20:54:03 2021-04-30 20:54:03 root -DYNAMIC_SUBNET 1.1.0.0/16 2021-04-30 20:54:03 2021-04-30 20:54:03 root -EMAIL_DOMAIN example.com 2021-04-30 20:54:03 2021-04-30 20:54:03 root -EMAIL_NOTIFICATION_INTERVAL 7 days 2021-04-30 20:54:03 2021-04-30 20:54:03 root -USER_PRIVILEGE_SOURCE local 2021-04-30 20:54:03 2021-04-30 20:54:03 root -WEB_URL https://starrs.example.com 2021-04-30 20:54:03 2021-04-30 20:54:03 root -\. - - --- --- Data for Name: group_members; Type: TABLE DATA; Schema: management; Owner: starrs_admin --- - -COPY group_members ("group", "user", privilege, date_created, date_modified, last_modifier) FROM stdin; -Administrators root ADMIN 2021-04-30 20:54:03 2021-04-30 20:54:03 root -Users root ADMIN 2021-04-30 20:54:03 2021-04-30 20:54:03 root -Users user USER 2021-04-30 20:54:03 2021-04-30 20:54:03 root -\. - - --- --- Data for Name: group_settings; Type: TABLE DATA; Schema: management; Owner: starrs_admin --- - -COPY group_settings ("group", privilege, provider, hostname, id, username, password, date_modified, date_created, last_modifier) FROM stdin; -\. - - --- --- Data for Name: groups; Type: TABLE DATA; Schema: management; Owner: starrs_admin --- - -COPY groups ("group", comment, privilege, renew_interval, date_created, date_modified, last_modifier) FROM stdin; -Administrators Admin users ADMIN 10 years 2021-04-30 20:54:03 2021-04-30 20:54:03 root -Users Regular users USER 1 year 2021-04-30 20:54:03 2021-04-30 20:54:03 root -\. - - --- --- Data for Name: log_master; Type: TABLE DATA; Schema: management; Owner: starrs_admin --- - -COPY log_master ("timestamp", "user", message, source, severity) FROM stdin; -\. - - --- --- Data for Name: output; Type: TABLE DATA; Schema: management; Owner: starrs_admin --- - -COPY output (output_id, value, file, "timestamp") FROM stdin; -\. - - --- --- Name: output_id_seq; Type: SEQUENCE SET; Schema: management; Owner: starrs_admin --- - -SELECT pg_catalog.setval('output_id_seq', 1, false); - - -SET search_path = network, pg_catalog; - --- --- Data for Name: cam_cache; Type: TABLE DATA; Schema: network; Owner: starrs_admin --- - -COPY cam_cache (system_name, mac, ifindex, vlan, date_created, date_modified, last_modifier) FROM stdin; -\. - - --- --- Data for Name: snmp; Type: TABLE DATA; Schema: network; Owner: starrs_admin --- - -COPY snmp (system_name, address, ro_community, rw_community, date_created, date_modified, last_modifier) FROM stdin; -\. - - --- --- Data for Name: snmp3; Type: TABLE DATA; Schema: network; Owner: starrs_admin --- - -COPY snmp3 (system_name, "user", auth_encryption, password, priv_encryption, priv_password, date_created, date_modified, last_modifier) FROM stdin; -\. - - --- --- Data for Name: vlans; Type: TABLE DATA; Schema: network; Owner: starrs_admin --- - -COPY vlans (datacenter, vlan, name, comment, date_modified, date_created, last_modifier) FROM stdin; -Rochester 1 Management Management VLAN 2021-04-30 20:54:03 2021-04-30 20:54:03 root -Rochester 49 49net Server room 2021-04-30 20:54:03 2021-04-30 20:54:03 root -Rochester 50 50net Users 2021-04-30 20:54:03 2021-04-30 20:54:03 root -\. - - -SET search_path = systems, pg_catalog; - --- --- Data for Name: architectures; Type: TABLE DATA; Schema: systems; Owner: starrs_admin --- - -COPY architectures (architecture, comment, date_created, date_modified, last_modifier) FROM stdin; -i386 Standard x86 2021-04-30 20:53:53 2021-04-30 20:53:53 root -x86_64 Normal 32/64 Mode 2021-04-30 20:53:53 2021-04-30 20:53:53 root -ia64 Intel Itanium 2021-04-30 20:53:53 2021-04-30 20:53:53 root -SPARC Sun/Oracle 2021-04-30 20:53:53 2021-04-30 20:53:53 root -ARM ARM devices 2021-04-30 20:53:53 2021-04-30 20:53:53 root -PowerPC PowerPC 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Other Other 2021-04-30 20:53:53 2021-04-30 20:53:53 root -\. - - --- --- Data for Name: availability_zones; Type: TABLE DATA; Schema: systems; Owner: starrs_admin --- - -COPY availability_zones (datacenter, zone, comment, date_created, date_modified, last_modifier) FROM stdin; -Rochester Corp Corporate network 2021-04-30 20:54:03 2021-04-30 20:54:03 root -Rochester Secure Secure network 2021-04-30 20:54:03 2021-04-30 20:54:03 root -\. - - --- --- Data for Name: datacenters; Type: TABLE DATA; Schema: systems; Owner: starrs_admin --- - -COPY datacenters (datacenter, comment, date_created, date_modified, last_modifier) FROM stdin; -Rochester Rochester NY USA 2021-04-30 20:54:03 2021-04-30 20:54:03 root -\. - - --- --- Data for Name: device_types; Type: TABLE DATA; Schema: systems; Owner: starrs_admin --- - -COPY device_types (type, family) FROM stdin; -Router Network -Firewall Network -Switch Network -Hub Network -Wireless Access Point Network -Desktop PC -Server PC -Virtual Machine PC -Laptop PC -Printer PC -Game Console PC -VM Host PC -\. - - --- --- Data for Name: interface_addresses; Type: TABLE DATA; Schema: systems; Owner: starrs_admin --- - -COPY interface_addresses (date_created, date_modified, comment, address, last_modifier, config, family, isprimary, renew_date, mac, class) FROM stdin; -\. - - --- --- Data for Name: interfaces; Type: TABLE DATA; Schema: systems; Owner: starrs_admin --- - -COPY interfaces (mac, comment, date_created, date_modified, last_modifier, system_name, name) FROM stdin; -\. - - --- --- Data for Name: os; Type: TABLE DATA; Schema: systems; Owner: starrs_admin --- - -COPY os (name, family, date_created, date_modified, last_modifier) FROM stdin; -Cisco IOS Other 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Windows XP Windows 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Windows Vista Windows 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Windows 7 Windows 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Windows Server 2003 Windows 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Windows Server 2008 Windows 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Windows Server 2008 R2 Windows 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Gentoo Linux 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Ubuntu Linux 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Fedora Linux 2021-04-30 20:53:53 2021-04-30 20:53:53 root -CentOS Linux 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Slackware Linux 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Arch Linux 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Exherbo Linux 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Scientific Linux 2021-04-30 20:53:53 2021-04-30 20:53:53 root -RHEL Linux 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Debian Linux 2021-04-30 20:53:53 2021-04-30 20:53:53 root -FreeBSD BSD 2021-04-30 20:53:53 2021-04-30 20:53:53 root -OpenBSD BSD 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Mac OS X Mac 2021-04-30 20:53:53 2021-04-30 20:53:53 root -NetBSD BSD 2021-04-30 20:53:53 2021-04-30 20:53:53 root -XBox Other 2021-04-30 20:53:53 2021-04-30 20:53:53 root -PS3 Other 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Wii Other 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Plan9 UNIX 2021-04-30 20:53:53 2021-04-30 20:53:53 root -GNU/Hurd UNIX 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Haiku Other 2021-04-30 20:53:53 2021-04-30 20:53:53 root -BeOS Other 2021-04-30 20:53:53 2021-04-30 20:53:53 root -OpenIndiana Solaris 2021-04-30 20:53:53 2021-04-30 20:53:53 root -OpenSolaris Solaris 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Solaris Solaris 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Illumos Solaris 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Vyatta Other 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Other Other 2021-04-30 20:53:53 2021-04-30 20:53:53 root -\. - - --- --- Data for Name: os_family; Type: TABLE DATA; Schema: systems; Owner: starrs_admin --- - -COPY os_family (family, date_created, date_modified, last_modifier) FROM stdin; -Windows 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Linux 2021-04-30 20:53:53 2021-04-30 20:53:53 root -BSD 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Mac 2021-04-30 20:53:53 2021-04-30 20:53:53 root -UNIX 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Solaris 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Other 2021-04-30 20:53:53 2021-04-30 20:53:53 root -\. - - --- --- Data for Name: platforms; Type: TABLE DATA; Schema: systems; Owner: starrs_admin --- - -COPY platforms (platform_name, architecture, disk, cpu, memory, date_created, date_modified, last_modifier) FROM stdin; -Custom Other Other Other 0 2021-04-30 20:53:53 2021-04-30 20:53:53 root -Dell PowerEdge 1750 i386 2x 18GB 2x Xeon 2.4GHz 2 2021-04-30 20:53:53 2021-04-30 20:53:53 root -\. - - --- --- Data for Name: systems; Type: TABLE DATA; Schema: systems; Owner: starrs_admin --- - -COPY systems (system_name, owner, "group", comment, date_created, date_modified, type, os_name, last_modifier, platform_name, asset, datacenter, location) FROM stdin; -\. - - -SET search_path = dhcp, pg_catalog; - --- --- Name: class_options_class_option_value_key; Type: CONSTRAINT; Schema: dhcp; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY class_options - ADD CONSTRAINT class_options_class_option_value_key UNIQUE (option, value, class); - - --- --- Name: CONSTRAINT class_options_class_option_value_key ON class_options; Type: COMMENT; Schema: dhcp; Owner: starrs_admin --- - -COMMENT ON CONSTRAINT class_options_class_option_value_key ON class_options IS 'No two directives can be the same'; - - --- --- Name: class_options_pkey; Type: CONSTRAINT; Schema: dhcp; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY class_options - ADD CONSTRAINT class_options_pkey PRIMARY KEY (option, value, class); - - --- --- Name: classes_pkey; Type: CONSTRAINT; Schema: dhcp; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY classes - ADD CONSTRAINT classes_pkey PRIMARY KEY (class); - - --- --- Name: config_types_pkey; Type: CONSTRAINT; Schema: dhcp; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY config_types - ADD CONSTRAINT config_types_pkey PRIMARY KEY (config); - - --- --- Name: global_options_pkey; Type: CONSTRAINT; Schema: dhcp; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY global_options - ADD CONSTRAINT global_options_pkey PRIMARY KEY (option); - - --- --- Name: range_options_pkey; Type: CONSTRAINT; Schema: dhcp; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY range_options - ADD CONSTRAINT range_options_pkey PRIMARY KEY (name, option); - - --- --- Name: subnet_option_subnet_option_value_key; Type: CONSTRAINT; Schema: dhcp; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY subnet_options - ADD CONSTRAINT subnet_option_subnet_option_value_key UNIQUE (option, value, subnet); - - --- --- Name: CONSTRAINT subnet_option_subnet_option_value_key ON subnet_options; Type: COMMENT; Schema: dhcp; Owner: starrs_admin --- - -COMMENT ON CONSTRAINT subnet_option_subnet_option_value_key ON subnet_options IS 'No two directives can be the same'; - - --- --- Name: subnet_options_pkey; Type: CONSTRAINT; Schema: dhcp; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY subnet_options - ADD CONSTRAINT subnet_options_pkey PRIMARY KEY (option, value, subnet); - - -SET search_path = dns, pg_catalog; - --- --- Name: a_address_zone_key; Type: CONSTRAINT; Schema: dns; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY a - ADD CONSTRAINT a_address_zone_key UNIQUE (address, zone); - - --- --- Name: CONSTRAINT a_address_zone_key ON a; Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON CONSTRAINT a_address_zone_key ON a IS 'Addresses in this table must be unique'; - - --- --- Name: a_hostname_zone_type_key; Type: CONSTRAINT; Schema: dns; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY a - ADD CONSTRAINT a_hostname_zone_type_key UNIQUE (hostname, type, zone); - - --- --- Name: CONSTRAINT a_hostname_zone_type_key ON a; Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON CONSTRAINT a_hostname_zone_type_key ON a IS 'Can only have 1 of each A or AAAA'; - - --- --- Name: a_pkey; Type: CONSTRAINT; Schema: dns; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY a - ADD CONSTRAINT a_pkey PRIMARY KEY (hostname, address, zone); - - --- --- Name: cname_alias_zone_key; Type: CONSTRAINT; Schema: dns; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY cname - ADD CONSTRAINT cname_alias_zone_key UNIQUE (alias, zone); - - --- --- Name: CONSTRAINT cname_alias_zone_key ON cname; Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON CONSTRAINT cname_alias_zone_key ON cname IS 'Cannot have two of the same alises in the same zone'; - - --- --- Name: cname_pkey; Type: CONSTRAINT; Schema: dns; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY cname - ADD CONSTRAINT cname_pkey PRIMARY KEY (alias, hostname, address, zone); - - --- --- Name: dns_mx_preference_zone_key; Type: CONSTRAINT; Schema: dns; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY mx - ADD CONSTRAINT dns_mx_preference_zone_key UNIQUE (preference, zone); - - --- --- Name: CONSTRAINT dns_mx_preference_zone_key ON mx; Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON CONSTRAINT dns_mx_preference_zone_key ON mx IS 'No two MX servers can have the same preference in a domain'; - - --- --- Name: dns_txt_hostname_zone_text_key; Type: CONSTRAINT; Schema: dns; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY txt - ADD CONSTRAINT dns_txt_hostname_zone_text_key UNIQUE (hostname, zone, text); - - --- --- Name: CONSTRAINT dns_txt_hostname_zone_text_key ON txt; Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON CONSTRAINT dns_txt_hostname_zone_text_key ON txt IS 'No duplicate TXT records'; - - --- --- Name: dns_zone_a_pkey; Type: CONSTRAINT; Schema: dns; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY zone_a - ADD CONSTRAINT dns_zone_a_pkey PRIMARY KEY (zone, type); - - --- --- Name: keys_pkey; Type: CONSTRAINT; Schema: dns; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY keys - ADD CONSTRAINT keys_pkey PRIMARY KEY (keyname); - - --- --- Name: mx_pkey; Type: CONSTRAINT; Schema: dns; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY mx - ADD CONSTRAINT mx_pkey PRIMARY KEY (hostname, address, zone); - - --- --- Name: ns_pkey; Type: CONSTRAINT; Schema: dns; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY ns - ADD CONSTRAINT ns_pkey PRIMARY KEY (zone, nameserver); - - --- --- Name: soa_pkey; Type: CONSTRAINT; Schema: dns; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY soa - ADD CONSTRAINT soa_pkey PRIMARY KEY (zone); - - --- --- Name: srv_alias_information_key; Type: CONSTRAINT; Schema: dns; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY srv - ADD CONSTRAINT srv_alias_information_key UNIQUE (port, weight, priority, alias, zone); - - --- --- Name: CONSTRAINT srv_alias_information_key ON srv; Type: COMMENT; Schema: dns; Owner: starrs_admin --- - -COMMENT ON CONSTRAINT srv_alias_information_key ON srv IS 'No duplicate infomation'; - - --- --- Name: srv_pkey; Type: CONSTRAINT; Schema: dns; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY srv - ADD CONSTRAINT srv_pkey PRIMARY KEY (alias, hostname, address, zone, priority, weight, port); - - --- --- Name: txt_pkey; Type: CONSTRAINT; Schema: dns; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY txt - ADD CONSTRAINT txt_pkey PRIMARY KEY (text, hostname, address, zone); - - --- --- Name: types_pkey; Type: CONSTRAINT; Schema: dns; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY types - ADD CONSTRAINT types_pkey PRIMARY KEY (type); - - --- --- Name: zone_txt_hostname_zone_text_key; Type: CONSTRAINT; Schema: dns; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY zone_txt - ADD CONSTRAINT zone_txt_hostname_zone_text_key UNIQUE (hostname, zone, text); - - --- --- Name: zones_pkey; Type: CONSTRAINT; Schema: dns; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY zones - ADD CONSTRAINT zones_pkey PRIMARY KEY (zone); - - -SET search_path = ip, pg_catalog; - --- --- Name: addresses_pkey; Type: CONSTRAINT; Schema: ip; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY addresses - ADD CONSTRAINT addresses_pkey PRIMARY KEY (address); - - --- --- Name: ip_range_group_pkey; Type: CONSTRAINT; Schema: ip; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY range_groups - ADD CONSTRAINT ip_range_group_pkey PRIMARY KEY (range_name, group_name); - - --- --- Name: range_uses_pkey; Type: CONSTRAINT; Schema: ip; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY range_uses - ADD CONSTRAINT range_uses_pkey PRIMARY KEY (use); - - --- --- Name: ranges_first_ip_key; Type: CONSTRAINT; Schema: ip; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY ranges - ADD CONSTRAINT ranges_first_ip_key UNIQUE (first_ip); - - --- --- Name: CONSTRAINT ranges_first_ip_key ON ranges; Type: COMMENT; Schema: ip; Owner: starrs_admin --- - -COMMENT ON CONSTRAINT ranges_first_ip_key ON ranges IS 'Unique starting IP''s'; - - --- --- Name: ranges_last_ip_key; Type: CONSTRAINT; Schema: ip; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY ranges - ADD CONSTRAINT ranges_last_ip_key UNIQUE (last_ip); - - --- --- Name: CONSTRAINT ranges_last_ip_key ON ranges; Type: COMMENT; Schema: ip; Owner: starrs_admin --- - -COMMENT ON CONSTRAINT ranges_last_ip_key ON ranges IS 'Unique ending IP''s'; - - --- --- Name: ranges_pkey; Type: CONSTRAINT; Schema: ip; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY ranges - ADD CONSTRAINT ranges_pkey PRIMARY KEY (name); - - --- --- Name: subnets_pkey; Type: CONSTRAINT; Schema: ip; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY subnets - ADD CONSTRAINT subnets_pkey PRIMARY KEY (subnet); - - -SET search_path = libvirt, pg_catalog; - --- --- Name: libvirt_hosts_pkey; Type: CONSTRAINT; Schema: libvirt; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY hosts - ADD CONSTRAINT libvirt_hosts_pkey PRIMARY KEY (system_name); - - --- --- Name: libvirt_platforms_name_pkey; Type: CONSTRAINT; Schema: libvirt; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY platforms - ADD CONSTRAINT libvirt_platforms_name_pkey PRIMARY KEY (platform_name); - - -SET search_path = management, pg_catalog; - --- --- Name: configuration_pkey; Type: CONSTRAINT; Schema: management; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY configuration - ADD CONSTRAINT configuration_pkey PRIMARY KEY (option); - - --- --- Name: group_settings_pkey; Type: CONSTRAINT; Schema: management; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY group_settings - ADD CONSTRAINT group_settings_pkey PRIMARY KEY ("group"); - - --- --- Name: management_group_members_pkey; Type: CONSTRAINT; Schema: management; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY group_members - ADD CONSTRAINT management_group_members_pkey PRIMARY KEY ("group", "user"); - - --- --- Name: management_groups_pkey; Type: CONSTRAINT; Schema: management; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY groups - ADD CONSTRAINT management_groups_pkey PRIMARY KEY ("group"); - - --- --- Name: output_pkey; Type: CONSTRAINT; Schema: management; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY output - ADD CONSTRAINT output_pkey PRIMARY KEY (output_id); - - -SET search_path = network, pg_catalog; - --- --- Name: network_snmp3_pkey; Type: CONSTRAINT; Schema: network; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY snmp3 - ADD CONSTRAINT network_snmp3_pkey PRIMARY KEY (system_name); - - --- --- Name: network_snmp_pkey; Type: CONSTRAINT; Schema: network; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY snmp - ADD CONSTRAINT network_snmp_pkey PRIMARY KEY (system_name); - - --- --- Name: network_vlans_pkey; Type: CONSTRAINT; Schema: network; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY vlans - ADD CONSTRAINT network_vlans_pkey PRIMARY KEY (datacenter, vlan); - - -SET search_path = systems, pg_catalog; - --- --- Name: device_types_pkey; Type: CONSTRAINT; Schema: systems; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY device_types - ADD CONSTRAINT device_types_pkey PRIMARY KEY (type); - - --- --- Name: interface_addresses_pkey; Type: CONSTRAINT; Schema: systems; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY interface_addresses - ADD CONSTRAINT interface_addresses_pkey PRIMARY KEY (address); - - --- --- Name: interfaces_pkey; Type: CONSTRAINT; Schema: systems; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY interfaces - ADD CONSTRAINT interfaces_pkey PRIMARY KEY (mac); - - --- --- Name: interfaces_system_name_name_key; Type: CONSTRAINT; Schema: systems; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY interfaces - ADD CONSTRAINT interfaces_system_name_name_key UNIQUE (system_name, name); - - --- --- Name: CONSTRAINT interfaces_system_name_name_key ON interfaces; Type: COMMENT; Schema: systems; Owner: starrs_admin --- - -COMMENT ON CONSTRAINT interfaces_system_name_name_key ON interfaces IS 'Inteface names must be unique on a system'; - - --- --- Name: os_family_pkey; Type: CONSTRAINT; Schema: systems; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY os_family - ADD CONSTRAINT os_family_pkey PRIMARY KEY (family); - - --- --- Name: os_pkey; Type: CONSTRAINT; Schema: systems; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY os - ADD CONSTRAINT os_pkey PRIMARY KEY (name); - - --- --- Name: systems_architecture_pkey; Type: CONSTRAINT; Schema: systems; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY architectures - ADD CONSTRAINT systems_architecture_pkey PRIMARY KEY (architecture); - - --- --- Name: systems_az_pkey; Type: CONSTRAINT; Schema: systems; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY availability_zones - ADD CONSTRAINT systems_az_pkey PRIMARY KEY (datacenter, zone); - - --- --- Name: systems_datacenter_pkey; Type: CONSTRAINT; Schema: systems; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY datacenters - ADD CONSTRAINT systems_datacenter_pkey PRIMARY KEY (datacenter); - - --- --- Name: systems_pkey; Type: CONSTRAINT; Schema: systems; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY systems - ADD CONSTRAINT systems_pkey PRIMARY KEY (system_name); - - --- --- Name: systems_platforms_pkey; Type: CONSTRAINT; Schema: systems; Owner: starrs_admin; Tablespace: --- - -ALTER TABLE ONLY platforms - ADD CONSTRAINT systems_platforms_pkey PRIMARY KEY (platform_name); - - -SET search_path = dns, pg_catalog; - --- --- Name: dns_a_delete_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_a_delete_queue AFTER DELETE ON a FOR EACH ROW EXECUTE PROCEDURE queue_delete(); - - --- --- Name: dns_a_insert; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_a_insert BEFORE INSERT ON a FOR EACH ROW EXECUTE PROCEDURE a_insert(); - - --- --- Name: dns_a_insert_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_a_insert_queue AFTER INSERT ON a FOR EACH ROW EXECUTE PROCEDURE queue_insert(); - - --- --- Name: dns_a_update; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_a_update BEFORE UPDATE ON a FOR EACH ROW EXECUTE PROCEDURE a_update(); - - --- --- Name: dns_a_update_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_a_update_queue AFTER UPDATE ON a FOR EACH ROW EXECUTE PROCEDURE queue_update(); - - --- --- Name: dns_cname_delete_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_cname_delete_queue AFTER DELETE ON cname FOR EACH ROW EXECUTE PROCEDURE queue_delete(); - - --- --- Name: dns_cname_insert; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_cname_insert BEFORE INSERT ON cname FOR EACH ROW EXECUTE PROCEDURE cname_insert(); - - --- --- Name: dns_cname_insert_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_cname_insert_queue AFTER INSERT ON cname FOR EACH ROW EXECUTE PROCEDURE queue_insert(); - - --- --- Name: dns_cname_update; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_cname_update BEFORE UPDATE ON cname FOR EACH ROW EXECUTE PROCEDURE cname_update(); - - --- --- Name: dns_cname_update_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_cname_update_queue AFTER UPDATE ON cname FOR EACH ROW EXECUTE PROCEDURE queue_update(); - - --- --- Name: dns_mx_delete_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_mx_delete_queue AFTER DELETE ON mx FOR EACH ROW EXECUTE PROCEDURE queue_delete(); - - --- --- Name: dns_mx_insert; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_mx_insert BEFORE INSERT ON mx FOR EACH ROW EXECUTE PROCEDURE mx_insert(); - - --- --- Name: dns_mx_insert_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_mx_insert_queue AFTER INSERT ON mx FOR EACH ROW EXECUTE PROCEDURE queue_insert(); - - --- --- Name: dns_mx_update; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_mx_update BEFORE UPDATE ON mx FOR EACH ROW EXECUTE PROCEDURE mx_update(); - - --- --- Name: dns_mx_update_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_mx_update_queue AFTER UPDATE ON mx FOR EACH ROW EXECUTE PROCEDURE queue_update(); - - --- --- Name: dns_ns_delete_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_ns_delete_queue AFTER DELETE ON ns FOR EACH ROW EXECUTE PROCEDURE ns_query_delete(); - - --- --- Name: dns_ns_insert_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_ns_insert_queue AFTER INSERT ON ns FOR EACH ROW EXECUTE PROCEDURE ns_query_insert(); - - --- --- Name: dns_ns_update_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_ns_update_queue AFTER UPDATE ON ns FOR EACH ROW EXECUTE PROCEDURE ns_query_update(); - - --- --- Name: dns_srv_delete_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_srv_delete_queue AFTER DELETE ON srv FOR EACH ROW EXECUTE PROCEDURE queue_delete(); - - --- --- Name: dns_srv_insert; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_srv_insert BEFORE INSERT ON srv FOR EACH ROW EXECUTE PROCEDURE srv_insert(); - - --- --- Name: dns_srv_insert_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_srv_insert_queue AFTER INSERT ON srv FOR EACH ROW EXECUTE PROCEDURE queue_insert(); - - --- --- Name: dns_srv_update; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_srv_update BEFORE UPDATE ON srv FOR EACH ROW EXECUTE PROCEDURE srv_update(); - - --- --- Name: dns_srv_update_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_srv_update_queue AFTER UPDATE ON srv FOR EACH ROW EXECUTE PROCEDURE queue_update(); - - --- --- Name: dns_txt_delete_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_txt_delete_queue AFTER DELETE ON txt FOR EACH ROW EXECUTE PROCEDURE txt_query_delete(); - - --- --- Name: dns_txt_insert; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_txt_insert BEFORE INSERT ON txt FOR EACH ROW EXECUTE PROCEDURE txt_insert(); - - --- --- Name: dns_txt_insert_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_txt_insert_queue AFTER INSERT ON txt FOR EACH ROW EXECUTE PROCEDURE txt_query_insert(); - - --- --- Name: dns_txt_update; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_txt_update BEFORE UPDATE ON txt FOR EACH ROW EXECUTE PROCEDURE txt_update(); - - --- --- Name: dns_txt_update_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_txt_update_queue AFTER UPDATE ON txt FOR EACH ROW EXECUTE PROCEDURE txt_query_update(); - - --- --- Name: dns_zone_a_delete; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_zone_a_delete BEFORE DELETE ON zone_a FOR EACH ROW EXECUTE PROCEDURE zone_a_delete(); - - --- --- Name: dns_zone_a_delete_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_zone_a_delete_queue AFTER DELETE ON zone_a FOR EACH ROW EXECUTE PROCEDURE queue_delete(); - - --- --- Name: dns_zone_a_insert; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_zone_a_insert BEFORE INSERT ON zone_a FOR EACH ROW EXECUTE PROCEDURE zone_a_insert(); - - --- --- Name: dns_zone_a_insert_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_zone_a_insert_queue AFTER INSERT ON zone_a FOR EACH ROW EXECUTE PROCEDURE queue_insert(); - - --- --- Name: dns_zone_a_update; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_zone_a_update BEFORE UPDATE ON zone_a FOR EACH ROW EXECUTE PROCEDURE zone_a_update(); - - --- --- Name: dns_zone_a_update_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_zone_a_update_queue AFTER UPDATE ON zone_a FOR EACH ROW EXECUTE PROCEDURE queue_update(); - - --- --- Name: dns_zone_txt_delete_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_zone_txt_delete_queue AFTER DELETE ON zone_txt FOR EACH ROW EXECUTE PROCEDURE txt_query_delete(); - - --- --- Name: dns_zone_txt_insert; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_zone_txt_insert BEFORE INSERT ON zone_txt FOR EACH ROW EXECUTE PROCEDURE zone_txt_insert(); - - --- --- Name: dns_zone_txt_insert_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_zone_txt_insert_queue AFTER INSERT ON zone_txt FOR EACH ROW EXECUTE PROCEDURE txt_query_insert(); - - --- --- Name: dns_zone_txt_update; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_zone_txt_update BEFORE UPDATE ON zone_txt FOR EACH ROW EXECUTE PROCEDURE zone_txt_update(); - - --- --- Name: dns_zone_txt_update_queue; Type: TRIGGER; Schema: dns; Owner: starrs_admin --- - -CREATE TRIGGER dns_zone_txt_update_queue AFTER UPDATE ON zone_txt FOR EACH ROW EXECUTE PROCEDURE txt_query_update(); - - -SET search_path = ip, pg_catalog; - --- --- Name: ip_addresses_insert; Type: TRIGGER; Schema: ip; Owner: starrs_admin --- - -CREATE TRIGGER ip_addresses_insert BEFORE INSERT ON addresses FOR EACH ROW EXECUTE PROCEDURE addresses_insert(); - - --- --- Name: ip_ranges_insert; Type: TRIGGER; Schema: ip; Owner: starrs_admin --- - -CREATE TRIGGER ip_ranges_insert BEFORE INSERT ON ranges FOR EACH ROW EXECUTE PROCEDURE ranges_insert(); - - --- --- Name: ip_ranges_update; Type: TRIGGER; Schema: ip; Owner: starrs_admin --- - -CREATE TRIGGER ip_ranges_update BEFORE UPDATE ON ranges FOR EACH ROW EXECUTE PROCEDURE ranges_update(); - - --- --- Name: ip_subnets_delete; Type: TRIGGER; Schema: ip; Owner: starrs_admin --- - -CREATE TRIGGER ip_subnets_delete BEFORE DELETE ON subnets FOR EACH ROW EXECUTE PROCEDURE subnets_delete(); - - --- --- Name: ip_subnets_insert; Type: TRIGGER; Schema: ip; Owner: starrs_admin --- - -CREATE TRIGGER ip_subnets_insert BEFORE INSERT ON subnets FOR EACH ROW EXECUTE PROCEDURE subnets_insert(); - - --- --- Name: ip_subnets_update; Type: TRIGGER; Schema: ip; Owner: starrs_admin --- - -CREATE TRIGGER ip_subnets_update BEFORE UPDATE ON subnets FOR EACH ROW EXECUTE PROCEDURE subnets_update(); - - -SET search_path = systems, pg_catalog; - --- --- Name: systems_interface_addresses_insert; Type: TRIGGER; Schema: systems; Owner: starrs_admin --- - -CREATE TRIGGER systems_interface_addresses_insert BEFORE INSERT ON interface_addresses FOR EACH ROW EXECUTE PROCEDURE interface_addresses_insert(); - - --- --- Name: systems_interface_addresses_update; Type: TRIGGER; Schema: systems; Owner: starrs_admin --- - -CREATE TRIGGER systems_interface_addresses_update BEFORE UPDATE ON interface_addresses FOR EACH ROW EXECUTE PROCEDURE interface_addresses_update(); - - -SET search_path = dhcp, pg_catalog; - --- --- Name: fk_dhcp_class_options_class; Type: FK CONSTRAINT; Schema: dhcp; Owner: starrs_admin --- - -ALTER TABLE ONLY class_options - ADD CONSTRAINT fk_dhcp_class_options_class FOREIGN KEY (class) REFERENCES classes(class) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_dhcp_subnet_options_subnet; Type: FK CONSTRAINT; Schema: dhcp; Owner: starrs_admin --- - -ALTER TABLE ONLY subnet_options - ADD CONSTRAINT fk_dhcp_subnet_options_subnet FOREIGN KEY (subnet) REFERENCES ip.subnets(subnet) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_range_options_name; Type: FK CONSTRAINT; Schema: dhcp; Owner: starrs_admin --- - -ALTER TABLE ONLY range_options - ADD CONSTRAINT fk_range_options_name FOREIGN KEY (name) REFERENCES ip.ranges(name) ON UPDATE CASCADE ON DELETE CASCADE; - - -SET search_path = dns, pg_catalog; - --- --- Name: fk_a_type; Type: FK CONSTRAINT; Schema: dns; Owner: starrs_admin --- - -ALTER TABLE ONLY a - ADD CONSTRAINT fk_a_type FOREIGN KEY (type) REFERENCES types(type) ON UPDATE RESTRICT ON DELETE RESTRICT; - - --- --- Name: fk_a_zone; Type: FK CONSTRAINT; Schema: dns; Owner: starrs_admin --- - -ALTER TABLE ONLY a - ADD CONSTRAINT fk_a_zone FOREIGN KEY (zone) REFERENCES zones(zone) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_cname_fqdn; Type: FK CONSTRAINT; Schema: dns; Owner: starrs_admin --- - -ALTER TABLE ONLY cname - ADD CONSTRAINT fk_cname_fqdn FOREIGN KEY (hostname, address, zone) REFERENCES a(hostname, address, zone) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_dns_a_address; Type: FK CONSTRAINT; Schema: dns; Owner: starrs_admin --- - -ALTER TABLE ONLY a - ADD CONSTRAINT fk_dns_a_address FOREIGN KEY (address) REFERENCES systems.interface_addresses(address) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_dns_ns_zone; Type: FK CONSTRAINT; Schema: dns; Owner: starrs_admin --- - -ALTER TABLE ONLY ns - ADD CONSTRAINT fk_dns_ns_zone FOREIGN KEY (zone) REFERENCES zones(zone) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_dns_zone_a_address; Type: FK CONSTRAINT; Schema: dns; Owner: starrs_admin --- - -ALTER TABLE ONLY zone_a - ADD CONSTRAINT fk_dns_zone_a_address FOREIGN KEY (address) REFERENCES systems.interface_addresses(address) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_dns_zones_keyname; Type: FK CONSTRAINT; Schema: dns; Owner: starrs_admin --- - -ALTER TABLE ONLY zones - ADD CONSTRAINT fk_dns_zones_keyname FOREIGN KEY (keyname) REFERENCES keys(keyname) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_mx_fqdn; Type: FK CONSTRAINT; Schema: dns; Owner: starrs_admin --- - -ALTER TABLE ONLY mx - ADD CONSTRAINT fk_mx_fqdn FOREIGN KEY (hostname, address, zone) REFERENCES a(hostname, address, zone) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_mx_type; Type: FK CONSTRAINT; Schema: dns; Owner: starrs_admin --- - -ALTER TABLE ONLY mx - ADD CONSTRAINT fk_mx_type FOREIGN KEY (type) REFERENCES types(type) ON UPDATE RESTRICT ON DELETE RESTRICT; - - --- --- Name: fk_soa_zone; Type: FK CONSTRAINT; Schema: dns; Owner: starrs_admin --- - -ALTER TABLE ONLY soa - ADD CONSTRAINT fk_soa_zone FOREIGN KEY (zone) REFERENCES zones(zone) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_srv_fqdn; Type: FK CONSTRAINT; Schema: dns; Owner: starrs_admin --- - -ALTER TABLE ONLY srv - ADD CONSTRAINT fk_srv_fqdn FOREIGN KEY (hostname, address, zone) REFERENCES a(hostname, address, zone) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_txt_fqdn; Type: FK CONSTRAINT; Schema: dns; Owner: starrs_admin --- - -ALTER TABLE ONLY txt - ADD CONSTRAINT fk_txt_fqdn FOREIGN KEY (hostname, address, zone) REFERENCES a(hostname, address, zone) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_txt_type; Type: FK CONSTRAINT; Schema: dns; Owner: starrs_admin --- - -ALTER TABLE ONLY txt - ADD CONSTRAINT fk_txt_type FOREIGN KEY (type) REFERENCES types(type) ON UPDATE RESTRICT ON DELETE RESTRICT; - - --- --- Name: fk_zone_a_type; Type: FK CONSTRAINT; Schema: dns; Owner: starrs_admin --- - -ALTER TABLE ONLY zone_a - ADD CONSTRAINT fk_zone_a_type FOREIGN KEY (type) REFERENCES types(type) ON UPDATE RESTRICT ON DELETE RESTRICT; - - --- --- Name: fk_zone_a_zone; Type: FK CONSTRAINT; Schema: dns; Owner: starrs_admin --- - -ALTER TABLE ONLY zone_a - ADD CONSTRAINT fk_zone_a_zone FOREIGN KEY (zone) REFERENCES zones(zone) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_zone_txt_zone; Type: FK CONSTRAINT; Schema: dns; Owner: starrs_admin --- - -ALTER TABLE ONLY zone_txt - ADD CONSTRAINT fk_zone_txt_zone FOREIGN KEY (zone) REFERENCES zones(zone) ON UPDATE CASCADE ON DELETE CASCADE; - - -SET search_path = ip, pg_catalog; - --- --- Name: fk_ip_ranges_subnet; Type: FK CONSTRAINT; Schema: ip; Owner: starrs_admin --- - -ALTER TABLE ONLY ranges - ADD CONSTRAINT fk_ip_ranges_subnet FOREIGN KEY (subnet) REFERENCES subnets(subnet) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_ip_ranges_use; Type: FK CONSTRAINT; Schema: ip; Owner: starrs_admin --- - -ALTER TABLE ONLY ranges - ADD CONSTRAINT fk_ip_ranges_use FOREIGN KEY (use) REFERENCES range_uses(use) ON UPDATE RESTRICT ON DELETE RESTRICT; - - --- --- Name: fk_range_group_name; Type: FK CONSTRAINT; Schema: ip; Owner: starrs_admin --- - -ALTER TABLE ONLY range_groups - ADD CONSTRAINT fk_range_group_name FOREIGN KEY (group_name) REFERENCES management.groups("group") ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_range_name; Type: FK CONSTRAINT; Schema: ip; Owner: starrs_admin --- - -ALTER TABLE ONLY range_groups - ADD CONSTRAINT fk_range_name FOREIGN KEY (range_name) REFERENCES ranges(name) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_range_zone; Type: FK CONSTRAINT; Schema: ip; Owner: starrs_admin --- - -ALTER TABLE ONLY ranges - ADD CONSTRAINT fk_range_zone FOREIGN KEY (datacenter, zone) REFERENCES systems.availability_zones(datacenter, zone) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_ranges_class; Type: FK CONSTRAINT; Schema: ip; Owner: starrs_admin --- - -ALTER TABLE ONLY ranges - ADD CONSTRAINT fk_ranges_class FOREIGN KEY (class) REFERENCES dhcp.classes(class) ON UPDATE CASCADE ON DELETE RESTRICT; - - --- --- Name: fk_subnet_vlans; Type: FK CONSTRAINT; Schema: ip; Owner: starrs_admin --- - -ALTER TABLE ONLY subnets - ADD CONSTRAINT fk_subnet_vlans FOREIGN KEY (datacenter, vlan) REFERENCES network.vlans(datacenter, vlan) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_subnets_datacenter; Type: FK CONSTRAINT; Schema: ip; Owner: starrs_admin --- - -ALTER TABLE ONLY subnets - ADD CONSTRAINT fk_subnets_datacenter FOREIGN KEY (datacenter) REFERENCES systems.datacenters(datacenter) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_subnets_zone; Type: FK CONSTRAINT; Schema: ip; Owner: starrs_admin --- - -ALTER TABLE ONLY subnets - ADD CONSTRAINT fk_subnets_zone FOREIGN KEY (zone) REFERENCES dns.zones(zone) ON UPDATE CASCADE ON DELETE SET DEFAULT; - - -SET search_path = libvirt, pg_catalog; - --- --- Name: fk_libvirt_host_name; Type: FK CONSTRAINT; Schema: libvirt; Owner: starrs_admin --- - -ALTER TABLE ONLY hosts - ADD CONSTRAINT fk_libvirt_host_name FOREIGN KEY (system_name) REFERENCES systems.systems(system_name) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_libvirt_platform_name; Type: FK CONSTRAINT; Schema: libvirt; Owner: starrs_admin --- - -ALTER TABLE ONLY platforms - ADD CONSTRAINT fk_libvirt_platform_name FOREIGN KEY (platform_name) REFERENCES systems.platforms(platform_name) ON UPDATE CASCADE ON DELETE CASCADE; - - -SET search_path = management, pg_catalog; - --- --- Name: fk_group_settings_group; Type: FK CONSTRAINT; Schema: management; Owner: starrs_admin --- - -ALTER TABLE ONLY group_settings - ADD CONSTRAINT fk_group_settings_group FOREIGN KEY ("group") REFERENCES groups("group") ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_management_group_members; Type: FK CONSTRAINT; Schema: management; Owner: starrs_admin --- - -ALTER TABLE ONLY group_members - ADD CONSTRAINT fk_management_group_members FOREIGN KEY ("group") REFERENCES groups("group") ON UPDATE CASCADE ON DELETE CASCADE; - - -SET search_path = network, pg_catalog; - --- --- Name: fk_network_vlan_datacenter; Type: FK CONSTRAINT; Schema: network; Owner: starrs_admin --- - -ALTER TABLE ONLY vlans - ADD CONSTRAINT fk_network_vlan_datacenter FOREIGN KEY (datacenter) REFERENCES systems.datacenters(datacenter) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_snmp_address; Type: FK CONSTRAINT; Schema: network; Owner: starrs_admin --- - -ALTER TABLE ONLY snmp - ADD CONSTRAINT fk_snmp_address FOREIGN KEY (address) REFERENCES systems.interface_addresses(address) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_snmp_system_name; Type: FK CONSTRAINT; Schema: network; Owner: starrs_admin --- - -ALTER TABLE ONLY snmp - ADD CONSTRAINT fk_snmp_system_name FOREIGN KEY (system_name) REFERENCES systems.systems(system_name) ON UPDATE CASCADE ON DELETE CASCADE; - - -SET search_path = systems, pg_catalog; - --- --- Name: fk_platforms_architectures_arch; Type: FK CONSTRAINT; Schema: systems; Owner: starrs_admin --- - -ALTER TABLE ONLY platforms - ADD CONSTRAINT fk_platforms_architectures_arch FOREIGN KEY (architecture) REFERENCES architectures(architecture) ON UPDATE CASCADE ON DELETE RESTRICT; - - --- --- Name: fk_system_group; Type: FK CONSTRAINT; Schema: systems; Owner: starrs_admin --- - -ALTER TABLE ONLY systems - ADD CONSTRAINT fk_system_group FOREIGN KEY ("group") REFERENCES management.groups("group") ON UPDATE CASCADE ON DELETE RESTRICT; - - --- --- Name: fk_systems_az_datacenter; Type: FK CONSTRAINT; Schema: systems; Owner: starrs_admin --- - -ALTER TABLE ONLY availability_zones - ADD CONSTRAINT fk_systems_az_datacenter FOREIGN KEY (datacenter) REFERENCES datacenters(datacenter) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_systems_datacenter; Type: FK CONSTRAINT; Schema: systems; Owner: starrs_admin --- - -ALTER TABLE ONLY systems - ADD CONSTRAINT fk_systems_datacenter FOREIGN KEY (datacenter) REFERENCES datacenters(datacenter) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_systems_interface_address_class; Type: FK CONSTRAINT; Schema: systems; Owner: starrs_admin --- - -ALTER TABLE ONLY interface_addresses - ADD CONSTRAINT fk_systems_interface_address_class FOREIGN KEY (class) REFERENCES dhcp.classes(class) ON UPDATE CASCADE ON DELETE RESTRICT; - - --- --- Name: fk_systems_interface_address_config; Type: FK CONSTRAINT; Schema: systems; Owner: starrs_admin --- - -ALTER TABLE ONLY interface_addresses - ADD CONSTRAINT fk_systems_interface_address_config FOREIGN KEY (config) REFERENCES dhcp.config_types(config) ON UPDATE RESTRICT ON DELETE RESTRICT; - - --- --- Name: fk_systems_interface_addresses_mac; Type: FK CONSTRAINT; Schema: systems; Owner: starrs_admin --- - -ALTER TABLE ONLY interface_addresses - ADD CONSTRAINT fk_systems_interface_addresses_mac FOREIGN KEY (mac) REFERENCES interfaces(mac) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_systems_interfaces_address; Type: FK CONSTRAINT; Schema: systems; Owner: starrs_admin --- - -ALTER TABLE ONLY interface_addresses - ADD CONSTRAINT fk_systems_interfaces_address FOREIGN KEY (address) REFERENCES ip.addresses(address) ON UPDATE RESTRICT ON DELETE RESTRICT DEFERRABLE; - - --- --- Name: fk_systems_interfaces_system_name; Type: FK CONSTRAINT; Schema: systems; Owner: starrs_admin --- - -ALTER TABLE ONLY interfaces - ADD CONSTRAINT fk_systems_interfaces_system_name FOREIGN KEY (system_name) REFERENCES systems(system_name) ON UPDATE CASCADE ON DELETE CASCADE; - - --- --- Name: fk_systems_os_family; Type: FK CONSTRAINT; Schema: systems; Owner: starrs_admin --- - -ALTER TABLE ONLY os - ADD CONSTRAINT fk_systems_os_family FOREIGN KEY (family) REFERENCES os_family(family) ON UPDATE RESTRICT ON DELETE RESTRICT; - - --- --- Name: fk_systems_platform; Type: FK CONSTRAINT; Schema: systems; Owner: starrs_admin --- - -ALTER TABLE ONLY systems - ADD CONSTRAINT fk_systems_platform FOREIGN KEY (platform_name) REFERENCES platforms(platform_name) ON UPDATE CASCADE ON DELETE RESTRICT; - - --- --- Name: fk_systems_systems_os; Type: FK CONSTRAINT; Schema: systems; Owner: starrs_admin --- - -ALTER TABLE ONLY systems - ADD CONSTRAINT fk_systems_systems_os FOREIGN KEY (os_name) REFERENCES os(name) ON UPDATE RESTRICT ON DELETE RESTRICT; - - --- --- Name: fk_systems_systems_type; Type: FK CONSTRAINT; Schema: systems; Owner: starrs_admin --- - -ALTER TABLE ONLY systems - ADD CONSTRAINT fk_systems_systems_type FOREIGN KEY (type) REFERENCES device_types(type) ON UPDATE RESTRICT ON DELETE RESTRICT; - - --- --- Name: api; Type: ACL; Schema: -; Owner: starrs_admin --- - -REVOKE ALL ON SCHEMA api FROM PUBLIC; -REVOKE ALL ON SCHEMA api FROM starrs_admin; -GRANT ALL ON SCHEMA api TO starrs_admin; -GRANT USAGE ON SCHEMA api TO starrs_client; - - --- --- Name: dhcp; Type: ACL; Schema: -; Owner: starrs_admin --- - -REVOKE ALL ON SCHEMA dhcp FROM PUBLIC; -REVOKE ALL ON SCHEMA dhcp FROM starrs_admin; -GRANT ALL ON SCHEMA dhcp TO starrs_admin; -GRANT USAGE ON SCHEMA dhcp TO starrs_client; - - --- --- Name: dns; Type: ACL; Schema: -; Owner: starrs_admin --- - -REVOKE ALL ON SCHEMA dns FROM PUBLIC; -REVOKE ALL ON SCHEMA dns FROM starrs_admin; -GRANT ALL ON SCHEMA dns TO starrs_admin; -GRANT USAGE ON SCHEMA dns TO starrs_client; - - --- --- Name: ip; Type: ACL; Schema: -; Owner: starrs_admin --- - -REVOKE ALL ON SCHEMA ip FROM PUBLIC; -REVOKE ALL ON SCHEMA ip FROM starrs_admin; -GRANT ALL ON SCHEMA ip TO starrs_admin; -GRANT USAGE ON SCHEMA ip TO starrs_client; - - --- --- Name: libvirt; Type: ACL; Schema: -; Owner: starrs_admin --- - -REVOKE ALL ON SCHEMA libvirt FROM PUBLIC; -REVOKE ALL ON SCHEMA libvirt FROM starrs_admin; -GRANT ALL ON SCHEMA libvirt TO starrs_admin; -GRANT USAGE ON SCHEMA libvirt TO starrs_client; - - --- --- Name: management; Type: ACL; Schema: -; Owner: starrs_admin --- - -REVOKE ALL ON SCHEMA management FROM PUBLIC; -REVOKE ALL ON SCHEMA management FROM starrs_admin; -GRANT ALL ON SCHEMA management TO starrs_admin; -GRANT USAGE ON SCHEMA management TO starrs_client; - - --- --- Name: network; Type: ACL; Schema: -; Owner: starrs_admin --- - -REVOKE ALL ON SCHEMA network FROM PUBLIC; -REVOKE ALL ON SCHEMA network FROM starrs_admin; -GRANT ALL ON SCHEMA network TO starrs_admin; -GRANT USAGE ON SCHEMA network TO starrs_client; - - --- --- Name: public; Type: ACL; Schema: -; Owner: postgres --- - -REVOKE ALL ON SCHEMA public FROM PUBLIC; -REVOKE ALL ON SCHEMA public FROM postgres; -GRANT ALL ON SCHEMA public TO postgres; -GRANT ALL ON SCHEMA public TO PUBLIC; - - --- --- Name: systems; Type: ACL; Schema: -; Owner: starrs_admin --- - -REVOKE ALL ON SCHEMA systems FROM PUBLIC; -REVOKE ALL ON SCHEMA systems FROM starrs_admin; -GRANT ALL ON SCHEMA systems TO starrs_admin; -GRANT USAGE ON SCHEMA systems TO starrs_client; - - --- --- Name: availability_zones; Type: ACL; Schema: systems; Owner: starrs_admin --- - -REVOKE ALL ON TABLE availability_zones FROM PUBLIC; -REVOKE ALL ON TABLE availability_zones FROM starrs_admin; -GRANT ALL ON TABLE availability_zones TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE availability_zones TO starrs_client; - - --- --- Name: datacenters; Type: ACL; Schema: systems; Owner: starrs_admin --- - -REVOKE ALL ON TABLE datacenters FROM PUBLIC; -REVOKE ALL ON TABLE datacenters FROM starrs_admin; -GRANT ALL ON TABLE datacenters TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE datacenters TO starrs_client; - - -SET search_path = dhcp, pg_catalog; - --- --- Name: classes; Type: ACL; Schema: dhcp; Owner: starrs_admin --- - -REVOKE ALL ON TABLE classes FROM PUBLIC; -REVOKE ALL ON TABLE classes FROM starrs_admin; -GRANT ALL ON TABLE classes TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE classes TO starrs_client; - - --- --- Name: class_options; Type: ACL; Schema: dhcp; Owner: starrs_admin --- - -REVOKE ALL ON TABLE class_options FROM PUBLIC; -REVOKE ALL ON TABLE class_options FROM starrs_admin; -GRANT ALL ON TABLE class_options TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE class_options TO starrs_client; - - --- --- Name: global_options; Type: ACL; Schema: dhcp; Owner: starrs_admin --- - -REVOKE ALL ON TABLE global_options FROM PUBLIC; -REVOKE ALL ON TABLE global_options FROM starrs_admin; -GRANT ALL ON TABLE global_options TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE global_options TO starrs_client; - - --- --- Name: range_options; Type: ACL; Schema: dhcp; Owner: starrs_admin --- - -REVOKE ALL ON TABLE range_options FROM PUBLIC; -REVOKE ALL ON TABLE range_options FROM starrs_admin; -GRANT ALL ON TABLE range_options TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE range_options TO starrs_client; - - --- --- Name: subnet_options; Type: ACL; Schema: dhcp; Owner: starrs_admin --- - -REVOKE ALL ON TABLE subnet_options FROM PUBLIC; -REVOKE ALL ON TABLE subnet_options FROM starrs_admin; -GRANT ALL ON TABLE subnet_options TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE subnet_options TO starrs_client; - - -SET search_path = dns, pg_catalog; - --- --- Name: a; Type: ACL; Schema: dns; Owner: starrs_admin --- - -REVOKE ALL ON TABLE a FROM PUBLIC; -REVOKE ALL ON TABLE a FROM starrs_admin; -GRANT ALL ON TABLE a TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE a TO starrs_client; - - --- --- Name: cname; Type: ACL; Schema: dns; Owner: starrs_admin --- - -REVOKE ALL ON TABLE cname FROM PUBLIC; -REVOKE ALL ON TABLE cname FROM starrs_admin; -GRANT ALL ON TABLE cname TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE cname TO starrs_client; - - --- --- Name: keys; Type: ACL; Schema: dns; Owner: starrs_admin --- - -REVOKE ALL ON TABLE keys FROM PUBLIC; -REVOKE ALL ON TABLE keys FROM starrs_admin; -GRANT ALL ON TABLE keys TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE keys TO starrs_client; - - --- --- Name: mx; Type: ACL; Schema: dns; Owner: starrs_admin --- - -REVOKE ALL ON TABLE mx FROM PUBLIC; -REVOKE ALL ON TABLE mx FROM starrs_admin; -GRANT ALL ON TABLE mx TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE mx TO starrs_client; - - --- --- Name: ns; Type: ACL; Schema: dns; Owner: starrs_admin --- - -REVOKE ALL ON TABLE ns FROM PUBLIC; -REVOKE ALL ON TABLE ns FROM starrs_admin; -GRANT ALL ON TABLE ns TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE ns TO starrs_client; - - --- --- Name: soa; Type: ACL; Schema: dns; Owner: starrs_admin --- - -REVOKE ALL ON TABLE soa FROM PUBLIC; -REVOKE ALL ON TABLE soa FROM starrs_admin; -GRANT ALL ON TABLE soa TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE soa TO starrs_client; - - --- --- Name: srv; Type: ACL; Schema: dns; Owner: starrs_admin --- - -REVOKE ALL ON TABLE srv FROM PUBLIC; -REVOKE ALL ON TABLE srv FROM starrs_admin; -GRANT ALL ON TABLE srv TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE srv TO starrs_client; - - --- --- Name: txt; Type: ACL; Schema: dns; Owner: starrs_admin --- - -REVOKE ALL ON TABLE txt FROM PUBLIC; -REVOKE ALL ON TABLE txt FROM starrs_admin; -GRANT ALL ON TABLE txt TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE txt TO starrs_client; - - --- --- Name: zones; Type: ACL; Schema: dns; Owner: starrs_admin --- - -REVOKE ALL ON TABLE zones FROM PUBLIC; -REVOKE ALL ON TABLE zones FROM starrs_admin; -GRANT ALL ON TABLE zones TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE zones TO starrs_client; - - --- --- Name: zone_a; Type: ACL; Schema: dns; Owner: starrs_admin --- - -REVOKE ALL ON TABLE zone_a FROM PUBLIC; -REVOKE ALL ON TABLE zone_a FROM starrs_admin; -GRANT ALL ON TABLE zone_a TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE zone_a TO starrs_client; - - --- --- Name: zone_txt; Type: ACL; Schema: dns; Owner: starrs_admin --- - -REVOKE ALL ON TABLE zone_txt FROM PUBLIC; -REVOKE ALL ON TABLE zone_txt FROM starrs_admin; -GRANT ALL ON TABLE zone_txt TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE zone_txt TO starrs_client; - - -SET search_path = management, pg_catalog; - --- --- Name: groups; Type: ACL; Schema: management; Owner: starrs_admin --- - -REVOKE ALL ON TABLE groups FROM PUBLIC; -REVOKE ALL ON TABLE groups FROM starrs_admin; -GRANT ALL ON TABLE groups TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE groups TO starrs_client; - - --- --- Name: group_members; Type: ACL; Schema: management; Owner: starrs_admin --- - -REVOKE ALL ON TABLE group_members FROM PUBLIC; -REVOKE ALL ON TABLE group_members FROM starrs_admin; -GRANT ALL ON TABLE group_members TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE group_members TO starrs_client; - - -SET search_path = systems, pg_catalog; - --- --- Name: interfaces; Type: ACL; Schema: systems; Owner: starrs_admin --- - -REVOKE ALL ON TABLE interfaces FROM PUBLIC; -REVOKE ALL ON TABLE interfaces FROM starrs_admin; -GRANT ALL ON TABLE interfaces TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE interfaces TO starrs_client; - - --- --- Name: interface_addresses; Type: ACL; Schema: systems; Owner: starrs_admin --- - -REVOKE ALL ON TABLE interface_addresses FROM PUBLIC; -REVOKE ALL ON TABLE interface_addresses FROM starrs_admin; -GRANT ALL ON TABLE interface_addresses TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE interface_addresses TO starrs_client; - - -SET search_path = ip, pg_catalog; - --- --- Name: ranges; Type: ACL; Schema: ip; Owner: starrs_admin --- - -REVOKE ALL ON TABLE ranges FROM PUBLIC; -REVOKE ALL ON TABLE ranges FROM starrs_admin; -GRANT ALL ON TABLE ranges TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE ranges TO starrs_client; - - --- --- Name: subnets; Type: ACL; Schema: ip; Owner: starrs_admin --- - -REVOKE ALL ON TABLE subnets FROM PUBLIC; -REVOKE ALL ON TABLE subnets FROM starrs_admin; -GRANT ALL ON TABLE subnets TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE subnets TO starrs_client; - - -SET search_path = libvirt, pg_catalog; - --- --- Name: hosts; Type: ACL; Schema: libvirt; Owner: starrs_admin --- - -REVOKE ALL ON TABLE hosts FROM PUBLIC; -REVOKE ALL ON TABLE hosts FROM starrs_admin; -GRANT ALL ON TABLE hosts TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE hosts TO starrs_client; - - -SET search_path = network, pg_catalog; - --- --- Name: snmp; Type: ACL; Schema: network; Owner: starrs_admin --- - -REVOKE ALL ON TABLE snmp FROM PUBLIC; -REVOKE ALL ON TABLE snmp FROM starrs_admin; -GRANT ALL ON TABLE snmp TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE snmp TO starrs_client; - - -SET search_path = systems, pg_catalog; - --- --- Name: platforms; Type: ACL; Schema: systems; Owner: starrs_admin --- - -REVOKE ALL ON TABLE platforms FROM PUBLIC; -REVOKE ALL ON TABLE platforms FROM starrs_admin; -GRANT ALL ON TABLE platforms TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE platforms TO starrs_client; - - -SET search_path = ip, pg_catalog; - --- --- Name: range_groups; Type: ACL; Schema: ip; Owner: starrs_admin --- - -REVOKE ALL ON TABLE range_groups FROM PUBLIC; -REVOKE ALL ON TABLE range_groups FROM starrs_admin; -GRANT ALL ON TABLE range_groups TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE range_groups TO starrs_client; - - -SET search_path = management, pg_catalog; - --- --- Name: configuration; Type: ACL; Schema: management; Owner: starrs_admin --- - -REVOKE ALL ON TABLE configuration FROM PUBLIC; -REVOKE ALL ON TABLE configuration FROM starrs_admin; -GRANT ALL ON TABLE configuration TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE configuration TO starrs_client; - - -SET search_path = systems, pg_catalog; - --- --- Name: systems; Type: ACL; Schema: systems; Owner: starrs_admin --- - -REVOKE ALL ON TABLE systems FROM PUBLIC; -REVOKE ALL ON TABLE systems FROM starrs_admin; -GRANT ALL ON TABLE systems TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE systems TO starrs_client; - - -SET search_path = network, pg_catalog; - --- --- Name: vlans; Type: ACL; Schema: network; Owner: starrs_admin --- - -REVOKE ALL ON TABLE vlans FROM PUBLIC; -REVOKE ALL ON TABLE vlans FROM starrs_admin; -GRANT ALL ON TABLE vlans TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vlans TO starrs_client; - - -SET search_path = dhcp, pg_catalog; - --- --- Name: config_types; Type: ACL; Schema: dhcp; Owner: starrs_admin --- - -REVOKE ALL ON TABLE config_types FROM PUBLIC; -REVOKE ALL ON TABLE config_types FROM starrs_admin; -GRANT ALL ON TABLE config_types TO starrs_admin; -GRANT SELECT ON TABLE config_types TO starrs_client; - - -SET search_path = network, pg_catalog; - --- --- Name: cam_cache; Type: ACL; Schema: network; Owner: starrs_admin --- - -REVOKE ALL ON TABLE cam_cache FROM PUBLIC; -REVOKE ALL ON TABLE cam_cache FROM starrs_admin; -GRANT ALL ON TABLE cam_cache TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE cam_cache TO starrs_client; - - -SET search_path = systems, pg_catalog; - --- --- Name: architectures; Type: ACL; Schema: systems; Owner: starrs_admin --- - -REVOKE ALL ON TABLE architectures FROM PUBLIC; -REVOKE ALL ON TABLE architectures FROM starrs_admin; -GRANT ALL ON TABLE architectures TO starrs_admin; -GRANT SELECT ON TABLE architectures TO starrs_client; - - --- --- Name: device_types; Type: ACL; Schema: systems; Owner: starrs_admin --- - -REVOKE ALL ON TABLE device_types FROM PUBLIC; -REVOKE ALL ON TABLE device_types FROM starrs_admin; -GRANT ALL ON TABLE device_types TO starrs_admin; -GRANT SELECT ON TABLE device_types TO starrs_client; - - -SET search_path = dns, pg_catalog; - --- --- Name: types; Type: ACL; Schema: dns; Owner: starrs_admin --- - -REVOKE ALL ON TABLE types FROM PUBLIC; -REVOKE ALL ON TABLE types FROM starrs_admin; -GRANT ALL ON TABLE types TO starrs_admin; -GRANT SELECT ON TABLE types TO starrs_client; - - -SET search_path = ip, pg_catalog; - --- --- Name: addresses; Type: ACL; Schema: ip; Owner: starrs_admin --- - -REVOKE ALL ON TABLE addresses FROM PUBLIC; -REVOKE ALL ON TABLE addresses FROM starrs_admin; -GRANT ALL ON TABLE addresses TO starrs_admin; -GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE addresses TO starrs_client; - - --- --- Name: range_uses; Type: ACL; Schema: ip; Owner: starrs_admin --- - -REVOKE ALL ON TABLE range_uses FROM PUBLIC; -REVOKE ALL ON TABLE range_uses FROM starrs_admin; -GRANT ALL ON TABLE range_uses TO starrs_admin; -GRANT SELECT ON TABLE range_uses TO starrs_client; - - -SET search_path = management, pg_catalog; - --- --- Name: log_master; Type: ACL; Schema: management; Owner: starrs_admin --- - -REVOKE ALL ON TABLE log_master FROM PUBLIC; -REVOKE ALL ON TABLE log_master FROM starrs_admin; -GRANT ALL ON TABLE log_master TO starrs_admin; -GRANT SELECT,INSERT ON TABLE log_master TO starrs_client; - - --- --- Name: output_id_seq; Type: ACL; Schema: management; Owner: starrs_admin --- - -REVOKE ALL ON SEQUENCE output_id_seq FROM PUBLIC; -REVOKE ALL ON SEQUENCE output_id_seq FROM starrs_admin; -GRANT ALL ON SEQUENCE output_id_seq TO starrs_admin; -GRANT SELECT,USAGE ON SEQUENCE output_id_seq TO starrs_client; - - --- --- Name: output; Type: ACL; Schema: management; Owner: starrs_admin --- - -REVOKE ALL ON TABLE output FROM PUBLIC; -REVOKE ALL ON TABLE output FROM starrs_admin; -GRANT ALL ON TABLE output TO starrs_admin; -GRANT SELECT,INSERT ON TABLE output TO starrs_client; - - -SET search_path = systems, pg_catalog; - --- --- Name: os; Type: ACL; Schema: systems; Owner: starrs_admin --- - -REVOKE ALL ON TABLE os FROM PUBLIC; -REVOKE ALL ON TABLE os FROM starrs_admin; -GRANT ALL ON TABLE os TO starrs_admin; -GRANT SELECT ON TABLE os TO starrs_client; - - --- --- Name: os_family; Type: ACL; Schema: systems; Owner: starrs_admin --- - -REVOKE ALL ON TABLE os_family FROM PUBLIC; -REVOKE ALL ON TABLE os_family FROM starrs_admin; -GRANT ALL ON TABLE os_family TO starrs_admin; -GRANT SELECT ON TABLE os_family TO starrs_client; - - --- --- PostgreSQL database dump complete --- - - diff --git a/developing/schema/starrs/old/starrs_schema b/developing/schema/starrs/old/starrs_schema deleted file mode 100644 index 7186a113ad3d4c2f59333453dbbd6d31a737894c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1085440 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�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�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 okj^VJk7}wWD>5BB1`Y+RPA~&k{p5Z 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

22vqU25$wsbMwBG%SESk^~!2 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 diff --git a/developing/schema/starrs/old/toc.dat b/developing/schema/starrs/old/toc.dat deleted file mode 100644 index 30d5fd11664392592093e7f223d27dfdeba5b6cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 568569 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 okj^VJk7}wWD>5BB1`Y+RPA~&k{p5Z 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

22vqU25$wsbMwBG%SESk^~!2 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 diff --git a/gunicorn_conf.py b/gunicorn_conf.py index fe4825b..0f569c9 100644 --- a/gunicorn_conf.py +++ b/gunicorn_conf.py @@ -4,8 +4,8 @@ import subprocess from flask import Flask app = Flask(__name__) -if os.path.exists(os.path.join(app.config.get('ROOT_DIR', os.getcwd()), "config.local.py")): - config = os.path.join(app.config.get('ROOT_DIR', os.getcwd()), "config.local.py") +if os.path.exists(os.path.join(app.config.get('ROOT_DIR', os.getcwd()), "config_local.py")): + config = os.path.join(app.config.get('ROOT_DIR', os.getcwd()), "config_local.py") else: config = os.path.join(app.config.get('ROOT_DIR', os.getcwd()), "config.py") app.config.from_pyfile(config) diff --git a/proxstar/__init__.py b/proxstar/__init__.py index 5482952..eb8dfee 100644 --- a/proxstar/__init__.py +++ b/proxstar/__init__.py @@ -158,6 +158,8 @@ def list_vms(user_view=None): user = User(session['userinfo']['preferred_username']) rtp_view = False connect_proxmox() + if eval(app.config['FORCE_STANDARD_USER']): + user.rtp = False if user_view and not user.rtp: abort(403) elif user_view and user.rtp: diff --git a/proxstar/proxmox.py b/proxstar/proxmox.py index fabc15c..7f9d207 100644 --- a/proxstar/proxmox.py +++ b/proxstar/proxmox.py @@ -60,7 +60,8 @@ def get_vm_node(proxmox, vmid): def get_isos(proxmox, storage): isos = [] - for iso in proxmox.nodes('proxmox01').storage(storage).content.get(): + first_node = app.config['PROXMOX_HOSTS'][0].split('.')[0] # Get the name of the first node. + for iso in proxmox.nodes(first_node).storage(storage).content.get(): isos.append(iso['volid'].split('/')[1]) return isos diff --git a/proxstar/tasks.py b/proxstar/tasks.py index af225d1..c24bfb8 100644 --- a/proxstar/tasks.py +++ b/proxstar/tasks.py @@ -83,11 +83,12 @@ def create_vm_task(user, name, cores, memory, disk, iso): set_job_status(job, 'failed to provision') delete_vm_task(vmid) return - logging.info('[{}] Registering in STARRS.'.format(name)) - set_job_status(job, 'registering in STARRS') vm = VM(vmid) - ip = get_next_ip(starrs, app.config['STARRS_IP_RANGE']) - register_starrs(starrs, name, app.config['STARRS_USER'], vm.get_mac(), ip) + if (eval(app.config['USE_STARRS'])): + logging.info('[{}] Registering in STARRS.'.format(name)) + set_job_status(job, 'registering in STARRS') + ip = get_next_ip(starrs, app.config['STARRS_IP_RANGE']) + register_starrs(starrs, name, app.config['STARRS_USER'], vm.get_mac(), ip) set_job_status(job, 'setting VM expiration') get_vm_expire(db, vmid, app.config['VM_EXPIRE_MONTHS']) vm.set_boot_order(['Hard Disk', 'CD-ROM', 'Network']) diff --git a/proxstar/vm.py b/proxstar/vm.py index 69ead65..482d589 100644 --- a/proxstar/vm.py +++ b/proxstar/vm.py @@ -250,8 +250,8 @@ def create_vm(proxmox, user, name, cores, memory, disk, iso): name=name, cores=cores, memory=memory, - storage='ceph', - virtio0='ceph:{}'.format(disk), + storage=app.config['PROXMOX_VM_STORAGE'], + virtio0='{}:{}'.format(app.config['PROXMOX_VM_STORAGE'], disk), ide2='{},media=cdrom'.format(iso), net0='virtio,bridge=vmbr0', pool=user,