use the SMTP library as advertised
[plcapi.git] / planetlab5.sql
1 --
2 -- PlanetLab Central database schema
3 -- Version 5, PostgreSQL
4 --
5 -- Aaron Klingaman <alk@cs.princeton.edu>
6 -- Reid Moran <rmoran@cs.princeton.edu>
7 -- Mark Huang <mlhuang@cs.princeton.edu>
8 -- Tony Mack <tmack@cs.princeton.edu>
9 -- Thierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
10 --
11 -- Copyright (C) 2006 The Trustees of Princeton University
12 --
13 -- NOTE: this file was first created for version 4.3, the filename might be confusing
14 --
15
16 SET client_encoding = 'UNICODE';
17
18 --------------------------------------------------------------------------------
19 -- Version
20 --------------------------------------------------------------------------------
21
22 -- Database version
23 CREATE TABLE plc_db_version (
24     version integer NOT NULL,
25     subversion integer NOT NULL DEFAULT 0
26 );
27
28 -- the migration scripts do not use the major 'version' number
29 -- so 5.0 sets subversion at 100
30 -- in case your database misses the site and persons tags feature,
31 -- you might wish to first upgrade to 4.3-rc16 before moving to some 5.0
32 -- or run the up script here
33 -- http://svn.planet-lab.org/svn/PLCAPI/branches/4.3/migrations/
34
35 INSERT INTO plc_db_version (version, subversion) VALUES (5, 100);
36
37 --------------------------------------------------------------------------------
38 -- Aggregates and store procedures
39 --------------------------------------------------------------------------------
40
41 -- Like MySQL GROUP_CONCAT(), this function aggregates values into a
42 -- PostgreSQL array.
43 CREATE AGGREGATE array_accum(anycompatible) (
44     sfunc = array_append,
45     stype = anycompatiblearray,
46     initcond = '{}'
47 );
48
49 --------------------------------------------------------------------------------
50 -- Roles
51 --------------------------------------------------------------------------------
52
53 -- Valid account roles
54 CREATE TABLE roles (
55     role_id integer PRIMARY KEY,                        -- Role identifier
56     name text UNIQUE NOT NULL                           -- Role symbolic name
57 );
58 INSERT INTO roles (role_id, name) VALUES (10, 'admin');
59 INSERT INTO roles (role_id, name) VALUES (20, 'pi');
60 INSERT INTO roles (role_id, name) VALUES (30, 'user');
61 INSERT INTO roles (role_id, name) VALUES (40, 'tech');
62
63 --------------------------------------------------------------------------------
64 -- The building block for attaching tags
65 --------------------------------------------------------------------------------
66 CREATE TABLE tag_types (
67
68     tag_type_id serial PRIMARY KEY,                     -- ID
69     tagname text UNIQUE NOT NULL,                       -- Tag Name
70     description text,                                   -- Optional Description
71 -- this is deprecated -- see migrations/104*
72 -- starting with subversion 104, a tag type has a SET OF roles attached to it
73     min_role_id integer REFERENCES roles DEFAULT 10,    -- set minimal role required
74     category text NOT NULL DEFAULT 'general'            -- Free text for grouping tags together
75 );
76
77 --------------------------------------------------------------------------------
78 -- Accounts
79 --------------------------------------------------------------------------------
80
81 -- Accounts
82 CREATE TABLE persons (
83     -- Mandatory
84     person_id serial PRIMARY KEY,                       -- Account identifier
85     email text NOT NULL,                                -- E-mail address
86     first_name text NOT NULL,                           -- First name
87     last_name text NOT NULL,                            -- Last name
88     deleted boolean NOT NULL DEFAULT false,             -- Has been deleted
89     enabled boolean NOT NULL DEFAULT false,             -- Has been disabled
90
91     password text NOT NULL DEFAULT 'nopass',            -- Password (md5crypted)
92     verification_key text,                              -- Reset password key
93     verification_expires timestamp without time zone,
94
95     -- Optional
96     title text,                                         -- Honorific
97     phone text,                                         -- Telephone number
98     url text,                                           -- Home page
99     bio text,                                           -- Biography
100
101     -- Timestamps
102     date_created timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
103     last_updated timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
104 );
105 CREATE INDEX persons_email_idx ON persons (email);
106
107 --------------------------------------------------------------------------------
108 -- person tags
109 --------------------------------------------------------------------------------
110 CREATE TABLE person_tag (
111     person_tag_id serial PRIMARY KEY,                   -- ID
112     person_id integer REFERENCES persons NOT NULL,      -- person id
113     tag_type_id integer REFERENCES tag_types,           -- tag type id
114     value text                                          -- value attached
115 );
116
117 CREATE OR REPLACE VIEW person_tags AS
118 SELECT person_id,
119 array_accum(person_tag_id) AS person_tag_ids
120 FROM person_tag
121 GROUP BY person_id;
122
123 CREATE OR REPLACE VIEW view_person_tags AS
124 SELECT
125 person_tag.person_tag_id,
126 person_tag.person_id,
127 persons.email,
128 tag_types.tag_type_id,
129 tag_types.tagname,
130 tag_types.description,
131 tag_types.category,
132 tag_types.min_role_id,
133 person_tag.value
134 FROM person_tag
135 INNER JOIN tag_types USING (tag_type_id)
136 INNER JOIN persons USING (person_id);
137
138 --------------------------------------------------------------------------------
139 -- Sites
140 --------------------------------------------------------------------------------
141
142 -- Sites
143 CREATE TABLE sites (
144     -- Mandatory
145     site_id serial PRIMARY KEY,                         -- Site identifier
146     login_base text NOT NULL,                           -- Site slice prefix
147     name text NOT NULL,                                 -- Site name
148     abbreviated_name text NOT NULL,                     -- Site abbreviated name
149     enabled boolean NOT NULL Default true,              -- Is this site enabled
150     deleted boolean NOT NULL DEFAULT false,             -- Has been deleted
151     is_public boolean NOT NULL DEFAULT true,            -- Shows up in public lists
152     max_slices integer NOT NULL DEFAULT 0,              -- Maximum number of slices
153     max_slivers integer NOT NULL DEFAULT 1000,          -- Maximum number of instantiated slivers
154
155     -- Optional
156     latitude real,
157     longitude real,
158     url text,
159     ext_consortium_id integer,                          -- external consortium id
160
161     -- Timestamps
162     date_created timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
163     last_updated timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
164 );
165 CREATE INDEX sites_login_base_idx ON sites (login_base);
166
167 -- Account site membership
168 CREATE TABLE person_site (
169     person_id integer REFERENCES persons NOT NULL,      -- Account identifier
170     site_id integer REFERENCES sites NOT NULL,          -- Site identifier
171     is_primary boolean NOT NULL DEFAULT false,          -- Is the primary site for this account
172     PRIMARY KEY (person_id, site_id)
173 );
174 CREATE INDEX person_site_person_id_idx ON person_site (person_id);
175 CREATE INDEX person_site_site_id_idx ON person_site (site_id);
176
177 -- Ordered by primary site first
178 CREATE OR REPLACE VIEW person_site_ordered AS
179 SELECT person_id, site_id
180 FROM person_site
181 ORDER BY is_primary DESC;
182
183 -- Sites that each person is a member of
184 CREATE OR REPLACE VIEW person_sites AS
185 SELECT person_id,
186 array_accum(site_id) AS site_ids
187 FROM person_site_ordered
188 GROUP BY person_id;
189
190 -- Accounts at each site
191 CREATE OR REPLACE VIEW site_persons AS
192 SELECT site_id,
193 array_accum(person_id) AS person_ids
194 FROM person_site
195 GROUP BY site_id;
196
197 --------------------------------------------------------------------------------
198 -- site tags
199 --------------------------------------------------------------------------------
200
201 CREATE TABLE site_tag (
202     site_tag_id serial PRIMARY KEY,                     -- ID
203     site_id integer REFERENCES sites NOT NULL,          -- site id
204     tag_type_id integer REFERENCES tag_types,           -- tag type id
205     value text                                          -- value attached
206 );
207
208 CREATE OR REPLACE VIEW site_tags AS
209 SELECT site_id,
210 array_accum(site_tag_id) AS site_tag_ids
211 FROM site_tag
212 GROUP BY site_id;
213
214 CREATE OR REPLACE VIEW view_site_tags AS
215 SELECT
216 site_tag.site_tag_id,
217 site_tag.site_id,
218 sites.login_base,
219 tag_types.tag_type_id,
220 tag_types.tagname,
221 tag_types.description,
222 tag_types.category,
223 tag_types.min_role_id,
224 site_tag.value
225 FROM site_tag
226 INNER JOIN tag_types USING (tag_type_id)
227 INNER JOIN sites USING (site_id);
228
229 --------------------------------------------------------------------------------
230 -- Mailing Addresses
231 --------------------------------------------------------------------------------
232
233 CREATE TABLE address_types (
234     address_type_id serial PRIMARY KEY,                 -- Address type identifier
235     name text UNIQUE NOT NULL,                          -- Address type
236     description text                                    -- Address type description
237 );
238
239 -- Multi-rows insertion "insert .. values (row1), (row2)" is not supported by pgsql-8.1
240 -- 'Billing' Used to be 'Site'
241 INSERT INTO address_types (name) VALUES ('Personal');
242 INSERT INTO address_types (name) VALUES ('Shipping');
243 INSERT INTO address_types (name) VALUES ('Billing');
244
245 -- Mailing addresses
246 CREATE TABLE addresses (
247     address_id serial PRIMARY KEY,                      -- Address identifier
248     line1 text NOT NULL,                                -- Address line 1
249     line2 text,                                         -- Address line 2
250     line3 text,                                         -- Address line 3
251     city text NOT NULL,                                 -- City
252     state text NOT NULL,                                -- State or province
253     postalcode text NOT NULL,                           -- Postal code
254     country text NOT NULL                               -- Country
255 );
256
257 -- Each mailing address can be one of several types
258 CREATE TABLE address_address_type (
259     address_id integer REFERENCES addresses NOT NULL,           -- Address identifier
260     address_type_id integer REFERENCES address_types NOT NULL,  -- Address type
261     PRIMARY KEY (address_id, address_type_id)
262 );
263 CREATE INDEX address_address_type_address_id_idx ON address_address_type (address_id);
264 CREATE INDEX address_address_type_address_type_id_idx ON address_address_type (address_type_id);
265
266 CREATE OR REPLACE VIEW address_address_types AS
267 SELECT address_id,
268 array_accum(address_type_id) AS address_type_ids,
269 array_accum(address_types.name) AS address_types
270 FROM address_address_type
271 LEFT JOIN address_types USING (address_type_id)
272 GROUP BY address_id;
273
274 CREATE TABLE site_address (
275     site_id integer REFERENCES sites NOT NULL,          -- Site identifier
276     address_id integer REFERENCES addresses NOT NULL,   -- Address identifier
277     PRIMARY KEY (site_id, address_id)
278 );
279 CREATE INDEX site_address_site_id_idx ON site_address (site_id);
280 CREATE INDEX site_address_address_id_idx ON site_address (address_id);
281
282 CREATE OR REPLACE VIEW site_addresses AS
283 SELECT site_id,
284 array_accum(address_id) AS address_ids
285 FROM site_address
286 GROUP BY site_id;
287
288 --------------------------------------------------------------------------------
289 -- Authentication Keys
290 --------------------------------------------------------------------------------
291
292 -- Valid key types
293 CREATE TABLE key_types (
294     key_type text PRIMARY KEY                           -- Key type
295 );
296 INSERT INTO key_types (key_type) VALUES ('ssh');
297
298 -- Authentication keys
299 CREATE TABLE keys (
300     key_id serial PRIMARY KEY,                          -- Key identifier
301     key_type text REFERENCES key_types NOT NULL,        -- Key type
302     key text NOT NULL, -- Key material
303     is_blacklisted boolean NOT NULL DEFAULT false       -- Has been blacklisted
304 );
305
306 -- Account authentication key(s)
307 CREATE TABLE person_key (
308     key_id integer REFERENCES keys PRIMARY KEY,         -- Key identifier
309     person_id integer REFERENCES persons NOT NULL       -- Account identifier
310 );
311 CREATE INDEX person_key_person_id_idx ON person_key (person_id);
312
313 CREATE OR REPLACE VIEW person_keys AS
314 SELECT person_id,
315 array_accum(key_id) AS key_ids
316 FROM person_key
317 GROUP BY person_id;
318
319 --------------------------------------------------------------------------------
320 -- Account roles
321 --------------------------------------------------------------------------------
322
323 CREATE TABLE person_role (
324     person_id integer REFERENCES persons NOT NULL,      -- Account identifier
325     role_id integer REFERENCES roles NOT NULL,          -- Role identifier
326     PRIMARY KEY (person_id, role_id)
327 );
328 CREATE INDEX person_role_person_id_idx ON person_role (person_id);
329
330 -- Account roles
331 CREATE OR REPLACE VIEW person_roles AS
332 SELECT person_id,
333 array_accum(role_id) AS role_ids,
334 array_accum(roles.name) AS roles
335 FROM person_role
336 LEFT JOIN roles USING (role_id)
337 GROUP BY person_id;
338
339 --------------------------------------------------------------------------------
340 -- Nodes
341 --------------------------------------------------------------------------------
342
343 -- Valid node boot states (Nodes.py expect max length to be 20)
344 CREATE TABLE boot_states (
345     boot_state text PRIMARY KEY
346 );
347 INSERT INTO boot_states (boot_state) VALUES ('boot');
348 INSERT INTO boot_states (boot_state) VALUES ('safeboot');
349 INSERT INTO boot_states (boot_state) VALUES ('reinstall');
350 INSERT INTO boot_states (boot_state) VALUES ('disabled');
351
352 CREATE TABLE run_levels  (
353     run_level text PRIMARY KEY
354 );
355 INSERT INTO run_levels  (run_level) VALUES ('boot');
356 INSERT INTO run_levels  (run_level) VALUES ('safeboot');
357 INSERT INTO run_levels  (run_level) VALUES ('failboot');
358 INSERT INTO run_levels  (run_level) VALUES ('reinstall');
359
360 -- Known node types (Nodes.py expect max length to be 20)
361 CREATE TABLE node_types (
362     node_type text PRIMARY KEY
363 );
364 INSERT INTO node_types (node_type) VALUES ('regular');
365 -- old dummynet stuff, to be removed
366 INSERT INTO node_types (node_type) VALUES ('dummynet');
367
368 -- Nodes
369 CREATE TABLE nodes (
370     -- Mandatory
371     node_id serial PRIMARY KEY,                         -- Node identifier
372     node_type text REFERENCES node_types                -- node type
373                DEFAULT 'regular',
374
375     hostname text NOT NULL,                             -- Node hostname
376     site_id integer REFERENCES sites NOT NULL,          -- At which site
377     boot_state text REFERENCES boot_states NOT NULL     -- Node boot state
378                DEFAULT 'reinstall',
379     run_level  text REFERENCES run_levels DEFAULT NULL, -- Node Run Level
380     deleted boolean NOT NULL DEFAULT false,             -- Is deleted
381
382     -- Optional
383     model text,                                         -- Hardware make and model
384     boot_nonce text,                                    -- Random nonce updated by Boot Manager
385     version text,                                       -- Boot CD version string updated by Boot Manager
386     ssh_rsa_key text,                                   -- SSH host key updated by Boot Manager
387     key text,                                           -- Node key generated when boot file is downloaded
388         verified boolean NOT NULL DEFAULT false,        -- whether or not the node & pcu are verified
389
390     -- Timestamps
391     date_created timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
392     last_updated timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
393     last_download timestamp without time zone,
394     last_pcu_reboot timestamp without time zone,
395     last_pcu_confirmation timestamp without time zone,
396     last_contact timestamp without time zone
397 );
398 CREATE INDEX nodes_hostname_idx ON nodes (hostname);
399 CREATE INDEX nodes_site_id_idx ON nodes (site_id);
400
401 -- Nodes at each site
402 CREATE OR REPLACE VIEW site_nodes AS
403 SELECT site_id,
404 array_accum(node_id) AS node_ids
405 FROM nodes
406 WHERE deleted IS false
407 GROUP BY site_id;
408
409 --------------------------------------------------------------------------------
410 -- node tags
411 --------------------------------------------------------------------------------
412
413 CREATE TABLE node_tag (
414     node_tag_id serial PRIMARY KEY,                     -- ID
415     node_id integer REFERENCES nodes NOT NULL,          -- node id
416     tag_type_id integer REFERENCES tag_types,           -- tag type id
417     value text                                          -- value attached
418 );
419
420 --------------------------------------------------------------------------------
421 -- (network) interfaces
422 --------------------------------------------------------------------------------
423
424 -- Valid network addressing schemes
425 CREATE TABLE network_types (
426     type text PRIMARY KEY -- Addressing scheme
427 );
428 INSERT INTO network_types (type) VALUES ('ipv4');
429
430 -- Valid network configuration methods
431 CREATE TABLE network_methods (
432     method text PRIMARY KEY -- Configuration method
433 );
434
435 INSERT INTO network_methods (method) VALUES ('static');
436 INSERT INTO network_methods (method) VALUES ('dhcp');
437 INSERT INTO network_methods (method) VALUES ('proxy');
438 INSERT INTO network_methods (method) VALUES ('tap');
439 INSERT INTO network_methods (method) VALUES ('ipmi');
440 INSERT INTO network_methods (method) VALUES ('unknown');
441
442 -- Network interfaces
443 CREATE TABLE interfaces (
444     -- Mandatory
445     interface_id serial PRIMARY KEY,                    -- Network interface identifier
446     node_id integer REFERENCES nodes NOT NULL,          -- Which node
447     is_primary boolean NOT NULL DEFAULT false,          -- Is the primary interface for this node
448     type text REFERENCES network_types NOT NULL,        -- Addressing scheme
449     method text REFERENCES network_methods NOT NULL,    -- Configuration method
450
451     -- Optional, depending on type and method
452     ip text,                                            -- IP address
453     mac text,                                           -- MAC address
454     gateway text,                                       -- Default gateway address
455     network text,                                       -- Network address
456     broadcast text,                                     -- Network broadcast address
457     netmask text,                                       -- Network mask
458     dns1 text,                                          -- Primary DNS server
459     dns2 text,                                          -- Secondary DNS server
460     bwlimit integer,                                    -- Bandwidth limit in bps
461     hostname text,                                      -- Hostname of this interface
462     last_updated timestamp without time zone -- When the interface was last updated
463 );
464 CREATE INDEX interfaces_node_id_idx ON interfaces (node_id);
465
466 -- Ordered by primary interface first
467 CREATE OR REPLACE VIEW interfaces_ordered AS
468 SELECT node_id, interface_id
469 FROM interfaces
470 ORDER BY is_primary DESC;
471
472 -- Network interfaces on each node
473 CREATE OR REPLACE VIEW node_interfaces AS
474 SELECT node_id,
475 array_accum(interface_id) AS interface_ids
476 FROM interfaces_ordered
477 GROUP BY node_id;
478
479 --------------------------------------------------------------------------------
480 -- Interface tags (formerly known as interface settings)
481 --------------------------------------------------------------------------------
482
483 CREATE TABLE interface_tag (
484     interface_tag_id serial PRIMARY KEY,                -- Interface Setting Identifier
485     interface_id integer REFERENCES interfaces NOT NULL,-- the interface this applies to
486     tag_type_id integer REFERENCES tag_types NOT NULL,  -- the setting type
487     value text                                          -- value attached
488 );
489
490 CREATE OR REPLACE VIEW interface_tags AS
491 SELECT interface_id,
492 array_accum(interface_tag_id) AS interface_tag_ids
493 FROM interface_tag
494 GROUP BY interface_id;
495
496 CREATE OR REPLACE VIEW view_interface_tags AS
497 SELECT
498 interface_tag.interface_tag_id,
499 interface_tag.interface_id,
500 interfaces.ip,
501 tag_types.tag_type_id,
502 tag_types.tagname,
503 tag_types.description,
504 tag_types.category,
505 tag_types.min_role_id,
506 interface_tag.value
507 FROM interface_tag
508 INNER JOIN tag_types USING (tag_type_id)
509 INNER JOIN interfaces USING (interface_id);
510
511 CREATE OR REPLACE VIEW view_interfaces AS
512 SELECT
513 interfaces.interface_id,
514 interfaces.node_id,
515 interfaces.is_primary,
516 interfaces.type,
517 interfaces.method,
518 interfaces.ip,
519 interfaces.mac,
520 interfaces.gateway,
521 interfaces.network,
522 interfaces.broadcast,
523 interfaces.netmask,
524 interfaces.dns1,
525 interfaces.dns2,
526 interfaces.bwlimit,
527 interfaces.hostname,
528 CAST(date_part('epoch', interfaces.last_updated) AS bigint) AS last_updated,
529 COALESCE((SELECT interface_tag_ids FROM interface_tags WHERE interface_tags.interface_id = interfaces.interface_id), '{}') AS interface_tag_ids
530 FROM interfaces;
531
532 --------------------------------------------------------------------------------
533 -- ilinks : links between interfaces
534 --------------------------------------------------------------------------------
535 CREATE TABLE ilink (
536        ilink_id serial PRIMARY KEY,                             -- id
537        tag_type_id integer REFERENCES tag_types,                -- id of the tag type
538        src_interface_id integer REFERENCES interfaces not NULL, -- id of src interface
539        dst_interface_id integer REFERENCES interfaces NOT NULL, -- id of dst interface
540        value text                                               -- optional value on the link
541 );
542
543 CREATE OR REPLACE VIEW view_ilinks AS
544 SELECT * FROM tag_types
545 INNER JOIN ilink USING (tag_type_id);
546
547 -- xxx TODO : expose to view_interfaces the set of ilinks a given interface is part of
548 -- this is needed for properly deleting these ilinks when an interface gets deleted
549 -- as this is not done yet, it prevents DeleteInterface, thus DeleteNode, thus DeleteSite
550 -- from working correctly when an iLink is set
551
552 --------------------------------------------------------------------------------
553 -- Node groups
554 --------------------------------------------------------------------------------
555
556 -- Node groups
557 CREATE TABLE nodegroups (
558     nodegroup_id serial PRIMARY KEY,            -- Group identifier
559     groupname text UNIQUE NOT NULL,             -- Group name
560     tag_type_id integer REFERENCES tag_types,   -- node is in nodegroup if it has this tag defined
561     -- can be null, make management faster & easier
562     value text                                  -- with this value attached
563 );
564
565 -- xxx - first rough implem. similar to former semantics but might be slow
566 CREATE OR REPLACE VIEW nodegroup_node AS
567 SELECT nodegroup_id, node_id
568 FROM tag_types
569 JOIN node_tag
570 USING (tag_type_id)
571 JOIN nodegroups
572 USING (tag_type_id,value);
573
574 CREATE OR REPLACE VIEW nodegroup_nodes AS
575 SELECT nodegroup_id,
576 array_accum(node_id) AS node_ids
577 FROM nodegroup_node
578 GROUP BY nodegroup_id;
579
580 -- Node groups that each node is a member of
581 CREATE OR REPLACE VIEW node_nodegroups AS
582 SELECT node_id,
583 array_accum(nodegroup_id) AS nodegroup_ids
584 FROM nodegroup_node
585 GROUP BY node_id;
586
587 --------------------------------------------------------------------------------
588 -- Node configuration files
589 --------------------------------------------------------------------------------
590
591 CREATE TABLE conf_files (
592     conf_file_id serial PRIMARY KEY,                    -- Configuration file identifier
593     enabled bool NOT NULL DEFAULT true,                 -- Configuration file is active
594     source text NOT NULL,                               -- Relative path on the boot server
595                                                         -- where file can be downloaded
596     dest text NOT NULL,                                 -- Absolute path where file should be installed
597     file_permissions text NOT NULL DEFAULT '0644',      -- chmod(1) permissions
598     file_owner text NOT NULL DEFAULT 'root',            -- chown(1) owner
599     file_group text NOT NULL DEFAULT 'root',            -- chgrp(1) owner
600     preinstall_cmd text,                                -- Shell command to execute prior to installing
601     postinstall_cmd text,                               -- Shell command to execute after installing
602     error_cmd text,                                     -- Shell command to execute if any error occurs
603     ignore_cmd_errors bool NOT NULL DEFAULT false,      -- Install file anyway even if an error occurs
604     always_update bool NOT NULL DEFAULT false           -- Always attempt to install file even if unchanged
605 );
606
607 CREATE TABLE conf_file_node (
608     conf_file_id integer REFERENCES conf_files NOT NULL,        -- Configuration file identifier
609     node_id integer REFERENCES nodes NOT NULL,                  -- Node identifier
610     PRIMARY KEY (conf_file_id, node_id)
611 );
612 CREATE INDEX conf_file_node_conf_file_id_idx ON conf_file_node (conf_file_id);
613 CREATE INDEX conf_file_node_node_id_idx ON conf_file_node (node_id);
614
615 -- Nodes linked to each configuration file
616 CREATE OR REPLACE VIEW conf_file_nodes AS
617 SELECT conf_file_id,
618 array_accum(node_id) AS node_ids
619 FROM conf_file_node
620 GROUP BY conf_file_id;
621
622 -- Configuration files linked to each node
623 CREATE OR REPLACE VIEW node_conf_files AS
624 SELECT node_id,
625 array_accum(conf_file_id) AS conf_file_ids
626 FROM conf_file_node
627 GROUP BY node_id;
628
629 CREATE TABLE conf_file_nodegroup (
630     conf_file_id integer REFERENCES conf_files NOT NULL,        -- Configuration file identifier
631     nodegroup_id integer REFERENCES nodegroups NOT NULL,        -- Node group identifier
632     PRIMARY KEY (conf_file_id, nodegroup_id)
633 );
634 CREATE INDEX conf_file_nodegroup_conf_file_id_idx ON conf_file_nodegroup (conf_file_id);
635 CREATE INDEX conf_file_nodegroup_nodegroup_id_idx ON conf_file_nodegroup (nodegroup_id);
636
637 -- Node groups linked to each configuration file
638 CREATE OR REPLACE VIEW conf_file_nodegroups AS
639 SELECT conf_file_id,
640 array_accum(nodegroup_id) AS nodegroup_ids
641 FROM conf_file_nodegroup
642 GROUP BY conf_file_id;
643
644 -- Configuration files linked to each node group
645 CREATE OR REPLACE VIEW nodegroup_conf_files AS
646 SELECT nodegroup_id,
647 array_accum(conf_file_id) AS conf_file_ids
648 FROM conf_file_nodegroup
649 GROUP BY nodegroup_id;
650
651 --------------------------------------------------------------------------------
652 -- Power control units (PCUs)
653 --------------------------------------------------------------------------------
654
655 CREATE TABLE pcus (
656     -- Mandatory
657     pcu_id serial PRIMARY KEY,                          -- PCU identifier
658     site_id integer REFERENCES sites NOT NULL,          -- Site identifier
659     hostname text,                                      -- Hostname, not necessarily unique
660                                                         -- (multiple logical sites could use the same PCU)
661     ip text NOT NULL,                                   -- IP, not necessarily unique
662
663     -- Optional
664     protocol text,                                      -- Protocol, e.g. ssh or https or telnet
665     username text,                                      -- Username, if applicable
666     "password" text,                                    -- Password, if applicable
667     model text,                                         -- Model, e.g. BayTech or iPal
668     last_updated timestamp without time zone,
669     notes text                                          -- Random notes
670 );
671 CREATE INDEX pcus_site_id_idx ON pcus (site_id);
672
673 CREATE OR REPLACE VIEW site_pcus AS
674 SELECT site_id,
675 array_accum(pcu_id) AS pcu_ids
676 FROM pcus
677 GROUP BY site_id;
678
679 CREATE TABLE pcu_node (
680     pcu_id integer REFERENCES pcus NOT NULL,            -- PCU identifier
681     node_id integer REFERENCES nodes NOT NULL,          -- Node identifier
682     port integer NOT NULL,                              -- Port number
683     PRIMARY KEY (pcu_id, node_id),                      -- The same node cannot be controlled by different ports
684     UNIQUE (pcu_id, port)                               -- The same port cannot control multiple nodes
685 );
686 CREATE INDEX pcu_node_pcu_id_idx ON pcu_node (pcu_id);
687 CREATE INDEX pcu_node_node_id_idx ON pcu_node (node_id);
688
689 CREATE OR REPLACE VIEW node_pcus AS
690 SELECT node_id,
691 array_accum(pcu_id) AS pcu_ids,
692 array_accum(port) AS ports
693 FROM pcu_node
694 GROUP BY node_id;
695
696 CREATE OR REPLACE VIEW pcu_nodes AS
697 SELECT pcu_id,
698 array_accum(node_id) AS node_ids,
699 array_accum(port) AS ports
700 FROM pcu_node
701 GROUP BY pcu_id;
702
703 --------------------------------------------------------------------------------
704 -- Slices
705 --------------------------------------------------------------------------------
706
707 CREATE TABLE slice_instantiations (
708     instantiation text PRIMARY KEY
709 );
710 INSERT INTO slice_instantiations (instantiation) VALUES ('not-instantiated');   -- Placeholder slice
711 INSERT INTO slice_instantiations (instantiation) VALUES ('plc-instantiated');   -- Instantiated by Node Manager
712 INSERT INTO slice_instantiations (instantiation) VALUES ('delegated');          -- Manually instantiated
713 INSERT INTO slice_instantiations (instantiation) VALUES ('nm-controller');      -- NM Controller
714
715 -- Slices
716 CREATE TABLE slices (
717     slice_id serial PRIMARY KEY,                        -- Slice identifier
718     site_id integer REFERENCES sites NOT NULL,          -- Site identifier
719
720     name text NOT NULL,                                 -- Slice name
721     instantiation text REFERENCES slice_instantiations  -- Slice state, e.g. plc-instantiated
722                   NOT NULL DEFAULT 'plc-instantiated',
723     url text,                                           -- Project URL
724     description text,                                   -- Project description
725
726     max_nodes integer NOT NULL DEFAULT 100,             -- Maximum number of nodes that can be assigned to this slice
727
728     creator_person_id integer REFERENCES persons,       -- Creator
729     created timestamp without time zone NOT NULL        -- Creation date
730         DEFAULT CURRENT_TIMESTAMP,
731     expires timestamp without time zone NOT NULL        -- Expiration date
732         DEFAULT CURRENT_TIMESTAMP + '2 weeks',
733
734     is_deleted boolean NOT NULL DEFAULT false
735 );
736 CREATE INDEX slices_site_id_idx ON slices (site_id);
737 CREATE INDEX slices_name_idx ON slices (name);
738
739 -- Slivers
740 CREATE TABLE slice_node (
741     slice_id integer REFERENCES slices NOT NULL,        -- Slice identifier
742     node_id integer REFERENCES nodes NOT NULL,          -- Node identifier
743     PRIMARY KEY (slice_id, node_id)
744 );
745 CREATE INDEX slice_node_slice_id_idx ON slice_node (slice_id);
746 CREATE INDEX slice_node_node_id_idx ON slice_node (node_id);
747
748 -- Synonym for slice_node
749 CREATE OR REPLACE VIEW slivers AS
750 SELECT * FROM slice_node;
751
752 -- Nodes in each slice
753 CREATE OR REPLACE VIEW slice_nodes AS
754 SELECT slice_id,
755 array_accum(node_id) AS node_ids
756 FROM slice_node
757 GROUP BY slice_id;
758
759 -- Slices on each node
760 CREATE OR REPLACE VIEW node_slices AS
761 SELECT node_id,
762 array_accum(slice_id) AS slice_ids
763 FROM slice_node
764 GROUP BY node_id;
765
766 -- Slices at each site
767 CREATE OR REPLACE VIEW site_slices AS
768 SELECT site_id,
769 array_accum(slice_id) AS slice_ids
770 FROM slices
771 WHERE is_deleted is false
772 GROUP BY site_id;
773
774 -- Slice membership
775 CREATE TABLE slice_person (
776     slice_id integer REFERENCES slices NOT NULL,        -- Slice identifier
777     person_id integer REFERENCES persons NOT NULL,      -- Account identifier
778     PRIMARY KEY (slice_id, person_id)
779 );
780 CREATE INDEX slice_person_slice_id_idx ON slice_person (slice_id);
781 CREATE INDEX slice_person_person_id_idx ON slice_person (person_id);
782
783 -- Members of the slice
784 CREATE OR REPLACE VIEW slice_persons AS
785 SELECT slice_id,
786 array_accum(person_id) AS person_ids
787 FROM slice_person
788 GROUP BY slice_id;
789
790 -- Slices of which each person is a member
791 CREATE OR REPLACE VIEW person_slices AS
792 SELECT person_id,
793 array_accum(slice_id) AS slice_ids
794 FROM slice_person
795 GROUP BY person_id;
796
797 --------------------------------------------------------------------------------
798 -- Slice whitelist
799 --------------------------------------------------------------------------------
800 -- slice whitelist on nodes
801 CREATE TABLE node_slice_whitelist (
802     node_id integer REFERENCES nodes NOT NULL,          -- Node id of whitelist
803     slice_id integer REFERENCES slices NOT NULL,        -- Slice id thats allowd on this node
804     PRIMARY KEY (node_id, slice_id)
805 );
806 CREATE INDEX node_slice_whitelist_node_id_idx ON node_slice_whitelist (node_id);
807 CREATE INDEX node_slice_whitelist_slice_id_idx ON node_slice_whitelist (slice_id);
808
809 -- Slices on each node
810 CREATE OR REPLACE VIEW node_slices_whitelist AS
811 SELECT node_id,
812 array_accum(slice_id) AS slice_ids_whitelist
813 FROM node_slice_whitelist
814 GROUP BY node_id;
815
816 --------------------------------------------------------------------------------
817 -- Slice tags (formerly known as slice attributes)
818 --------------------------------------------------------------------------------
819
820 -- Slice/sliver attributes
821 CREATE TABLE slice_tag (
822     slice_tag_id serial PRIMARY KEY,                    -- Slice attribute identifier
823     slice_id integer REFERENCES slices NOT NULL,        -- Slice identifier
824     node_id integer REFERENCES nodes,                   -- Sliver attribute if set
825     nodegroup_id integer REFERENCES nodegroups,         -- Node group attribute if set
826     tag_type_id integer REFERENCES tag_types NOT NULL,  -- Attribute type identifier
827     value text
828 );
829 CREATE INDEX slice_tag_slice_id_idx ON slice_tag (slice_id);
830 CREATE INDEX slice_tag_node_id_idx ON slice_tag (node_id);
831 CREATE INDEX slice_tag_nodegroup_id_idx ON slice_tag (nodegroup_id);
832
833 --------------------------------------------------------------------------------
834 -- Initscripts
835 --------------------------------------------------------------------------------
836
837 -- Initscripts
838 CREATE TABLE initscripts (
839     initscript_id serial PRIMARY KEY,                   -- Initscript identifier
840     name text NOT NULL,                                 -- Initscript name
841     enabled bool NOT NULL DEFAULT true,                 -- Initscript is active
842     script text NOT NULL,                               -- Initscript code
843     UNIQUE (name)
844 );
845 CREATE INDEX initscripts_name_idx ON initscripts (name);
846
847
848 --------------------------------------------------------------------------------
849 -- Peers
850 --------------------------------------------------------------------------------
851
852 -- Peers
853 CREATE TABLE peers (
854     peer_id serial PRIMARY KEY,                         -- Peer identifier
855     peername text NOT NULL,                             -- Peer name
856     peer_url text NOT NULL,                             -- (HTTPS) URL of the peer PLCAPI interface
857     cacert text,                                        -- (SSL) Public certificate of peer API server
858     key text,                                           -- (GPG) Public key used for authentication
859     shortname text,                                     -- abbreviated name for displaying foreign objects
860     hrn_root text,                                      -- root for this peer domain
861     deleted boolean NOT NULL DEFAULT false
862 );
863 CREATE INDEX peers_peername_idx ON peers (peername) WHERE deleted IS false;
864 CREATE INDEX peers_shortname_idx ON peers (shortname) WHERE deleted IS false;
865
866 -- Objects at each peer
867 CREATE TABLE peer_site (
868     site_id integer REFERENCES sites PRIMARY KEY,       -- Local site identifier
869     peer_id integer REFERENCES peers NOT NULL,          -- Peer identifier
870     peer_site_id integer NOT NULL,                      -- Foreign site identifier at peer
871     UNIQUE (peer_id, peer_site_id)                      -- The same foreign site should not be cached twice
872 );
873 CREATE INDEX peer_site_peer_id_idx ON peers (peer_id);
874
875 CREATE OR REPLACE VIEW peer_sites AS
876 SELECT peer_id,
877 array_accum(site_id) AS site_ids,
878 array_accum(peer_site_id) AS peer_site_ids
879 FROM peer_site
880 GROUP BY peer_id;
881
882 CREATE TABLE peer_person (
883     person_id integer REFERENCES persons PRIMARY KEY,   -- Local user identifier
884     peer_id integer REFERENCES peers NOT NULL,          -- Peer identifier
885     peer_person_id integer NOT NULL,                    -- Foreign user identifier at peer
886     UNIQUE (peer_id, peer_person_id)                    -- The same foreign user should not be cached twice
887 );
888 CREATE INDEX peer_person_peer_id_idx ON peer_person (peer_id);
889
890 CREATE OR REPLACE VIEW peer_persons AS
891 SELECT peer_id,
892 array_accum(person_id) AS person_ids,
893 array_accum(peer_person_id) AS peer_person_ids
894 FROM peer_person
895 GROUP BY peer_id;
896
897 CREATE TABLE peer_key (
898     key_id integer REFERENCES keys PRIMARY KEY,         -- Local key identifier
899     peer_id integer REFERENCES peers NOT NULL,          -- Peer identifier
900     peer_key_id integer NOT NULL,                       -- Foreign key identifier at peer
901     UNIQUE (peer_id, peer_key_id)                       -- The same foreign key should not be cached twice
902 );
903 CREATE INDEX peer_key_peer_id_idx ON peer_key (peer_id);
904
905 CREATE OR REPLACE VIEW peer_keys AS
906 SELECT peer_id,
907 array_accum(key_id) AS key_ids,
908 array_accum(peer_key_id) AS peer_key_ids
909 FROM peer_key
910 GROUP BY peer_id;
911
912 CREATE TABLE peer_node (
913     node_id integer REFERENCES nodes PRIMARY KEY,       -- Local node identifier
914     peer_id integer REFERENCES peers NOT NULL,          -- Peer identifier
915     peer_node_id integer NOT NULL,                      -- Foreign node identifier
916     UNIQUE (peer_id, peer_node_id)                      -- The same foreign node should not be cached twice
917 );
918 CREATE INDEX peer_node_peer_id_idx ON peer_node (peer_id);
919
920 CREATE OR REPLACE VIEW peer_nodes AS
921 SELECT peer_id,
922 array_accum(node_id) AS node_ids,
923 array_accum(peer_node_id) AS peer_node_ids
924 FROM peer_node
925 GROUP BY peer_id;
926
927 CREATE TABLE peer_slice (
928     slice_id integer REFERENCES slices PRIMARY KEY,     -- Local slice identifier
929     peer_id integer REFERENCES peers NOT NULL,          -- Peer identifier
930     peer_slice_id integer NOT NULL,                     -- Slice identifier at peer
931     UNIQUE (peer_id, peer_slice_id)                     -- The same foreign slice should not be cached twice
932 );
933 CREATE INDEX peer_slice_peer_id_idx ON peer_slice (peer_id);
934
935 CREATE OR REPLACE VIEW peer_slices AS
936 SELECT peer_id,
937 array_accum(slice_id) AS slice_ids,
938 array_accum(peer_slice_id) AS peer_slice_ids
939 FROM peer_slice
940 GROUP BY peer_id;
941
942 --------------------------------------------------------------------------------
943 -- Authenticated sessions
944 --------------------------------------------------------------------------------
945
946 -- Authenticated sessions
947 CREATE TABLE sessions (
948     session_id text PRIMARY KEY,                        -- Session identifier
949     expires timestamp without time zone
950 );
951
952 -- People can have multiple sessions
953 CREATE TABLE person_session (
954     person_id integer REFERENCES persons NOT NULL,      -- Account identifier
955     session_id text REFERENCES sessions NOT NULL,       -- Session identifier
956     PRIMARY KEY (person_id, session_id),
957     UNIQUE (session_id)                                 -- Sessions are unique
958 );
959 CREATE INDEX person_session_person_id_idx ON person_session (person_id);
960
961 -- Nodes can have only one session
962 CREATE TABLE node_session (
963     node_id integer REFERENCES nodes NOT NULL,          -- Node identifier
964     session_id text REFERENCES sessions NOT NULL,       -- Session identifier
965     UNIQUE (node_id),                                   -- Nodes can have only one session
966     UNIQUE (session_id)                                 -- Sessions are unique
967 );
968
969 -------------------------------------------------------------------------------
970 -- PCU Types
971 ------------------------------------------------------------------------------
972 CREATE TABLE pcu_types (
973     pcu_type_id serial PRIMARY KEY,
974     model text NOT NULL ,                               -- PCU model name
975     name text                                           -- Full PCU model name
976 );
977 CREATE INDEX pcu_types_model_idx ON pcu_types (model);
978
979 CREATE TABLE pcu_protocol_type (
980     pcu_protocol_type_id serial PRIMARY KEY,
981     pcu_type_id integer REFERENCES pcu_types NOT NULL,  -- PCU type identifier
982     port integer NOT NULL,                              -- PCU port
983     protocol text NOT NULL,                             -- Protocol
984     supported boolean NOT NULL DEFAULT True             -- Does PLC support
985 );
986 CREATE INDEX pcu_protocol_type_pcu_type_id ON pcu_protocol_type (pcu_type_id);
987
988
989 CREATE OR REPLACE VIEW pcu_protocol_types AS
990 SELECT pcu_type_id,
991 array_accum(pcu_protocol_type_id) as pcu_protocol_type_ids
992 FROM pcu_protocol_type
993 GROUP BY pcu_type_id;
994
995 --------------------------------------------------------------------------------
996 -- Message templates
997 --------------------------------------------------------------------------------
998
999 CREATE TABLE messages (
1000     message_id text PRIMARY KEY,                        -- Message name
1001     subject text,                                       -- Message summary
1002     template text,                                      -- Message template
1003     enabled bool NOT NULL DEFAULT true                  -- Whether message is enabled
1004 );
1005
1006 --------------------------------------------------------------------------------
1007 -- Events
1008 --------------------------------------------------------------------------------
1009
1010 -- Events
1011 CREATE TABLE events (
1012     event_id serial PRIMARY KEY,                        -- Event identifier
1013     person_id integer REFERENCES persons,               -- Person responsible for event, if any
1014     node_id integer REFERENCES nodes,                   -- Node responsible for event, if any
1015     auth_type text,                                     -- Type of auth used. i.e. AuthMethod
1016     fault_code integer NOT NULL DEFAULT 0,              -- Did this event result in error
1017     call_name text NOT NULL,                            -- Call responsible for this event
1018     call text NOT NULL,                                 -- Call responsible for this event, including parameters
1019     message text,                                       -- High level description of this event
1020     runtime float DEFAULT 0,                            -- Event run time
1021     time timestamp without time zone NOT NULL           -- Event timestamp
1022         DEFAULT CURRENT_TIMESTAMP
1023 );
1024
1025 -- Database object(s) that may have been affected by a particular event
1026 CREATE TABLE event_object (
1027     event_id integer REFERENCES events NOT NULL,        -- Event identifier
1028     object_id integer NOT NULL,                         -- Object identifier
1029     object_type text NOT NULL Default 'Unknown'         -- What type of object is this event affecting
1030 );
1031 CREATE INDEX event_object_event_id_idx ON event_object (event_id);
1032 CREATE INDEX event_object_object_id_idx ON event_object (object_id);
1033 CREATE INDEX event_object_object_type_idx ON event_object (object_type);
1034
1035 CREATE OR REPLACE VIEW event_objects AS
1036 SELECT event_id,
1037 array_accum(object_id) AS object_ids,
1038 array_accum(object_type) AS object_types
1039 FROM event_object
1040 GROUP BY event_id;
1041
1042 --------------------------------------------------------------------------------
1043 -- Useful views
1044 --------------------------------------------------------------------------------
1045 CREATE OR REPLACE VIEW view_pcu_types AS
1046 SELECT
1047 pcu_types.pcu_type_id,
1048 pcu_types.model,
1049 pcu_types.name,
1050 COALESCE((SELECT pcu_protocol_type_ids FROM pcu_protocol_types
1051                  WHERE pcu_protocol_types.pcu_type_id = pcu_types.pcu_type_id), '{}')
1052 AS pcu_protocol_type_ids
1053 FROM pcu_types;
1054
1055 --------------------------------------------------------------------------------
1056 CREATE OR REPLACE VIEW view_events AS
1057 SELECT
1058 events.event_id,
1059 events.person_id,
1060 events.node_id,
1061 events.auth_type,
1062 events.fault_code,
1063 events.call_name,
1064 events.call,
1065 events.message,
1066 events.runtime,
1067 CAST(date_part('epoch', events.time) AS bigint) AS time,
1068 COALESCE((SELECT object_ids FROM event_objects WHERE event_objects.event_id = events.event_id), '{}') AS object_ids,
1069 COALESCE((SELECT object_types FROM event_objects WHERE event_objects.event_id = events.event_id), '{}') AS object_types
1070 FROM events;
1071
1072 CREATE OR REPLACE VIEW view_event_objects AS
1073 SELECT
1074 events.event_id,
1075 events.person_id,
1076 events.node_id,
1077 events.fault_code,
1078 events.call_name,
1079 events.call,
1080 events.message,
1081 events.runtime,
1082 CAST(date_part('epoch', events.time) AS bigint) AS time,
1083 event_object.object_id,
1084 event_object.object_type
1085 FROM events LEFT JOIN event_object USING (event_id);
1086
1087 --------------------------------------------------------------------------------
1088 CREATE OR REPLACE VIEW view_persons AS
1089 SELECT
1090 persons.person_id,
1091 persons.email,
1092 persons.first_name,
1093 persons.last_name,
1094 persons.deleted,
1095 persons.enabled,
1096 persons.password,
1097 persons.verification_key,
1098 CAST(date_part('epoch', persons.verification_expires) AS bigint) AS verification_expires,
1099 persons.title,
1100 persons.phone,
1101 persons.url,
1102 persons.bio,
1103 CAST(date_part('epoch', persons.date_created) AS bigint) AS date_created,
1104 CAST(date_part('epoch', persons.last_updated) AS bigint) AS last_updated,
1105 peer_person.peer_id,
1106 peer_person.peer_person_id,
1107 COALESCE((SELECT role_ids FROM person_roles WHERE person_roles.person_id = persons.person_id), '{}') AS role_ids,
1108 COALESCE((SELECT roles FROM person_roles WHERE person_roles.person_id = persons.person_id), '{}') AS roles,
1109 COALESCE((SELECT site_ids FROM person_sites WHERE person_sites.person_id = persons.person_id), '{}') AS site_ids,
1110 COALESCE((SELECT key_ids FROM person_keys WHERE person_keys.person_id = persons.person_id), '{}') AS key_ids,
1111 COALESCE((SELECT slice_ids FROM person_slices WHERE person_slices.person_id = persons.person_id), '{}') AS slice_ids,
1112 COALESCE((SELECT person_tag_ids FROM person_tags WHERE person_tags.person_id = persons.person_id), '{}') AS person_tag_ids
1113 FROM persons
1114 LEFT JOIN peer_person USING (person_id);
1115
1116 --------------------------------------------------------------------------------
1117 CREATE OR REPLACE VIEW view_peers AS
1118 SELECT
1119 peers.*,
1120 COALESCE((SELECT site_ids FROM peer_sites WHERE peer_sites.peer_id = peers.peer_id), '{}') AS site_ids,
1121 COALESCE((SELECT peer_site_ids FROM peer_sites WHERE peer_sites.peer_id = peers.peer_id), '{}') AS peer_site_ids,
1122 COALESCE((SELECT person_ids FROM peer_persons WHERE peer_persons.peer_id = peers.peer_id), '{}') AS person_ids,
1123 COALESCE((SELECT peer_person_ids FROM peer_persons WHERE peer_persons.peer_id = peers.peer_id), '{}') AS peer_person_ids,
1124 COALESCE((SELECT key_ids FROM peer_keys WHERE peer_keys.peer_id = peers.peer_id), '{}') AS key_ids,
1125 COALESCE((SELECT peer_key_ids FROM peer_keys WHERE peer_keys.peer_id = peers.peer_id), '{}') AS peer_key_ids,
1126 COALESCE((SELECT node_ids FROM peer_nodes WHERE peer_nodes.peer_id = peers.peer_id), '{}') AS node_ids,
1127 COALESCE((SELECT peer_node_ids FROM peer_nodes WHERE peer_nodes.peer_id = peers.peer_id), '{}') AS peer_node_ids,
1128 COALESCE((SELECT slice_ids FROM peer_slices WHERE peer_slices.peer_id = peers.peer_id), '{}') AS slice_ids,
1129 COALESCE((SELECT peer_slice_ids FROM peer_slices WHERE peer_slices.peer_id = peers.peer_id), '{}') AS peer_slice_ids
1130 FROM peers;
1131
1132 --------------------------------------------------------------------------------
1133 CREATE OR REPLACE VIEW node_tags AS
1134 SELECT node_id,
1135 array_accum(node_tag_id) AS node_tag_ids
1136 FROM node_tag
1137 GROUP BY node_id;
1138
1139 CREATE OR REPLACE VIEW view_node_tags AS
1140 SELECT
1141 node_tag.node_tag_id,
1142 node_tag.node_id,
1143 nodes.hostname,
1144 tag_types.tag_type_id,
1145 tag_types.tagname,
1146 tag_types.description,
1147 tag_types.category,
1148 tag_types.min_role_id,
1149 node_tag.value
1150 FROM node_tag
1151 INNER JOIN tag_types USING (tag_type_id)
1152 INNER JOIN nodes USING (node_id);
1153
1154 CREATE OR REPLACE VIEW view_nodes AS
1155 SELECT
1156 nodes.node_id,
1157 nodes.node_type,
1158 nodes.hostname,
1159 nodes.site_id,
1160 nodes.boot_state,
1161 nodes.run_level,
1162 nodes.deleted,
1163 nodes.model,
1164 nodes.boot_nonce,
1165 nodes.version,
1166 nodes.verified,
1167 nodes.ssh_rsa_key,
1168 nodes.key,
1169 CAST(date_part('epoch', nodes.date_created) AS bigint) AS date_created,
1170 CAST(date_part('epoch', nodes.last_updated) AS bigint) AS last_updated,
1171 CAST(date_part('epoch', nodes.last_contact) AS bigint) AS last_contact,
1172 CAST(date_part('epoch', nodes.last_download) AS bigint) AS last_download,
1173 CAST(date_part('epoch', nodes.last_pcu_reboot) AS bigint) AS last_pcu_reboot,
1174 CAST(date_part('epoch', nodes.last_pcu_confirmation) AS bigint) AS last_pcu_confirmation,
1175 peer_node.peer_id,
1176 peer_node.peer_node_id,
1177 COALESCE((SELECT interface_ids FROM node_interfaces
1178                  WHERE node_interfaces.node_id = nodes.node_id), '{}')
1179 AS interface_ids,
1180 COALESCE((SELECT nodegroup_ids FROM node_nodegroups
1181                  WHERE node_nodegroups.node_id = nodes.node_id), '{}')
1182 AS nodegroup_ids,
1183 COALESCE((SELECT slice_ids FROM node_slices
1184                  WHERE node_slices.node_id = nodes.node_id), '{}')
1185 AS slice_ids,
1186 COALESCE((SELECT slice_ids_whitelist FROM node_slices_whitelist
1187                  WHERE node_slices_whitelist.node_id = nodes.node_id), '{}')
1188 AS slice_ids_whitelist,
1189 COALESCE((SELECT pcu_ids FROM node_pcus
1190                  WHERE node_pcus.node_id = nodes.node_id), '{}')
1191 AS pcu_ids,
1192 COALESCE((SELECT ports FROM node_pcus
1193                  WHERE node_pcus.node_id = nodes.node_id), '{}')
1194 AS ports,
1195 COALESCE((SELECT conf_file_ids FROM node_conf_files
1196                  WHERE node_conf_files.node_id = nodes.node_id), '{}')
1197 AS conf_file_ids,
1198 COALESCE((SELECT node_tag_ids FROM node_tags
1199                  WHERE node_tags.node_id = nodes.node_id), '{}')
1200 AS node_tag_ids,
1201 node_session.session_id AS session
1202 FROM nodes
1203 LEFT JOIN peer_node USING (node_id)
1204 LEFT JOIN node_session USING (node_id);
1205
1206 --------------------------------------------------------------------------------
1207 CREATE OR REPLACE VIEW view_nodegroups AS
1208 SELECT
1209 nodegroups.*,
1210 tag_types.tagname,
1211 COALESCE((SELECT conf_file_ids FROM nodegroup_conf_files
1212                  WHERE nodegroup_conf_files.nodegroup_id = nodegroups.nodegroup_id), '{}')
1213 AS conf_file_ids,
1214 COALESCE((SELECT node_ids FROM nodegroup_nodes
1215                  WHERE nodegroup_nodes.nodegroup_id = nodegroups.nodegroup_id), '{}')
1216 AS node_ids
1217 FROM nodegroups INNER JOIN tag_types USING (tag_type_id);
1218
1219 --------------------------------------------------------------------------------
1220 CREATE OR REPLACE VIEW view_conf_files AS
1221 SELECT
1222 conf_files.*,
1223 COALESCE((SELECT node_ids FROM conf_file_nodes
1224                  WHERE conf_file_nodes.conf_file_id = conf_files.conf_file_id), '{}')
1225 AS node_ids,
1226 COALESCE((SELECT nodegroup_ids FROM conf_file_nodegroups
1227                  WHERE conf_file_nodegroups.conf_file_id = conf_files.conf_file_id), '{}')
1228 AS nodegroup_ids
1229 FROM conf_files;
1230
1231 --------------------------------------------------------------------------------
1232 CREATE OR REPLACE VIEW view_pcus AS
1233 SELECT
1234 pcus.pcu_id,
1235 pcus.site_id,
1236 pcus.hostname,
1237 pcus.ip,
1238 pcus.protocol,
1239 pcus.username,
1240 pcus.password,
1241 pcus.model,
1242 pcus.notes,
1243 CAST(date_part('epoch', pcus.last_updated) AS bigint) AS last_updated,
1244 COALESCE((SELECT node_ids FROM pcu_nodes WHERE pcu_nodes.pcu_id = pcus.pcu_id), '{}') AS node_ids,
1245 COALESCE((SELECT ports FROM pcu_nodes WHERE pcu_nodes.pcu_id = pcus.pcu_id), '{}') AS ports
1246 FROM pcus;
1247
1248
1249 --------------------------------------------------------------------------------
1250 CREATE OR REPLACE VIEW view_sites AS
1251 SELECT
1252 sites.site_id,
1253 sites.login_base,
1254 sites.name,
1255 sites.abbreviated_name,
1256 sites.deleted,
1257 sites.enabled,
1258 sites.is_public,
1259 sites.max_slices,
1260 sites.max_slivers,
1261 sites.latitude,
1262 sites.longitude,
1263 sites.url,
1264 sites.ext_consortium_id,
1265 CAST(date_part('epoch', sites.date_created) AS bigint) AS date_created,
1266 CAST(date_part('epoch', sites.last_updated) AS bigint) AS last_updated,
1267 peer_site.peer_id,
1268 peer_site.peer_site_id,
1269 COALESCE((SELECT person_ids FROM site_persons WHERE site_persons.site_id = sites.site_id), '{}') AS person_ids,
1270 COALESCE((SELECT node_ids FROM site_nodes WHERE site_nodes.site_id = sites.site_id), '{}') AS node_ids,
1271 COALESCE((SELECT address_ids FROM site_addresses WHERE site_addresses.site_id = sites.site_id), '{}') AS address_ids,
1272 COALESCE((SELECT slice_ids FROM site_slices WHERE site_slices.site_id = sites.site_id), '{}') AS slice_ids,
1273 COALESCE((SELECT pcu_ids FROM site_pcus WHERE site_pcus.site_id = sites.site_id), '{}') AS pcu_ids,
1274 COALESCE((SELECT site_tag_ids FROM site_tags WHERE site_tags.site_id = sites.site_id), '{}') AS site_tag_ids
1275 FROM sites
1276 LEFT JOIN peer_site USING (site_id);
1277
1278 --------------------------------------------------------------------------------
1279 CREATE OR REPLACE VIEW view_addresses AS
1280 SELECT
1281 addresses.*,
1282 COALESCE((SELECT address_type_ids FROM address_address_types WHERE address_address_types.address_id = addresses.address_id), '{}') AS address_type_ids,
1283 COALESCE((SELECT address_types FROM address_address_types WHERE address_address_types.address_id = addresses.address_id), '{}') AS address_types
1284 FROM addresses;
1285
1286 --------------------------------------------------------------------------------
1287 CREATE OR REPLACE VIEW view_keys AS
1288 SELECT
1289 keys.*,
1290 person_key.person_id,
1291 peer_key.peer_id,
1292 peer_key.peer_key_id
1293 FROM keys
1294 LEFT JOIN person_key USING (key_id)
1295 LEFT JOIN peer_key USING (key_id);
1296
1297 --------------------------------------------------------------------------------
1298 CREATE OR REPLACE VIEW slice_tags AS
1299 SELECT slice_id,
1300 array_accum(slice_tag_id) AS slice_tag_ids
1301 FROM slice_tag
1302 GROUP BY slice_id;
1303
1304 CREATE OR REPLACE VIEW view_slices AS
1305 SELECT
1306 slices.slice_id,
1307 slices.site_id,
1308 slices.name,
1309 slices.instantiation,
1310 slices.url,
1311 slices.description,
1312 slices.max_nodes,
1313 slices.creator_person_id,
1314 slices.is_deleted,
1315 CAST(date_part('epoch', slices.created) AS bigint) AS created,
1316 CAST(date_part('epoch', slices.expires) AS bigint) AS expires,
1317 peer_slice.peer_id,
1318 peer_slice.peer_slice_id,
1319 COALESCE((SELECT node_ids FROM slice_nodes WHERE slice_nodes.slice_id = slices.slice_id), '{}') AS node_ids,
1320 COALESCE((SELECT person_ids FROM slice_persons WHERE slice_persons.slice_id = slices.slice_id), '{}') AS person_ids,
1321 COALESCE((SELECT slice_tag_ids FROM slice_tags WHERE slice_tags.slice_id = slices.slice_id), '{}') AS slice_tag_ids
1322 FROM slices
1323 LEFT JOIN peer_slice USING (slice_id);
1324
1325 CREATE OR REPLACE VIEW view_slice_tags AS
1326 SELECT
1327 slice_tag.slice_tag_id,
1328 slice_tag.slice_id,
1329 slice_tag.node_id,
1330 slice_tag.nodegroup_id,
1331 tag_types.tag_type_id,
1332 tag_types.tagname,
1333 tag_types.description,
1334 tag_types.category,
1335 tag_types.min_role_id,
1336 slice_tag.value,
1337 slices.name
1338 FROM slice_tag
1339 INNER JOIN tag_types USING (tag_type_id)
1340 INNER JOIN slices USING (slice_id);
1341
1342 --------------------------------------------------------------------------------
1343 CREATE OR REPLACE VIEW view_sessions AS
1344 SELECT
1345 sessions.session_id,
1346 CAST(date_part('epoch', sessions.expires) AS bigint) AS expires,
1347 person_session.person_id,
1348 node_session.node_id
1349 FROM sessions
1350 LEFT JOIN person_session USING (session_id)
1351 LEFT JOIN node_session USING (session_id);
1352
1353 --------------------------------------------------------------------------------
1354 -- Built-in maintenance account and default site
1355 --------------------------------------------------------------------------------
1356
1357 INSERT INTO persons (first_name, last_name, email, password, enabled)
1358 VALUES              ('Maintenance', 'Account', 'maint@localhost.localdomain', 'nopass', true);
1359
1360 INSERT INTO person_role (person_id, role_id) VALUES (1, 10);
1361 INSERT INTO person_role (person_id, role_id) VALUES (1, 20);
1362 INSERT INTO person_role (person_id, role_id) VALUES (1, 30);
1363 INSERT INTO person_role (person_id, role_id) VALUES (1, 40);
1364
1365 INSERT INTO sites (login_base, name, abbreviated_name, max_slices)
1366 VALUES ('pl', 'PlanetLab Central', 'PLC', 100);