first draft for node tags & new node groups:
[plcapi.git] / migrations / migrate-v4-to-v5.sh
1 #!/bin/bash
2
3 . /etc/planetlab/plc_config
4
5 PLC_DB_USER
6
7 # return 0 (yes) or 1 (no) whether the database exists
8 function check_for_database () {
9     dbname=$1; shift
10     psql --user=$PLC_DB_USER --quiet -c "SELECT subversion from plc_db_version LIMIT 1" $dbname 2> /dev/null
11     return $?
12 }
13
14 # when 'service plc start' gets run, the planetlab5 DB gets created 
15 # so this script will drop the planetlab5 DB and re-create it from scratch 
16 # with the contents of the planetlab4 DB that is epxected to exist
17 function main () {
18     
19     set -e
20     cd /usr/share/plc_api
21
22     # check that planetlab4 exists
23     if check_for_database planetlab4 ; then
24         echo OK : FOUND db planetlab4
25     else
26         echo ERROR :  planetlab4 NOT FOUND - exiting 
27         exit 1
28     fi
29
30     # dump planetlab4
31     DUMP4=planetlab4-$(date +%Y-%m-%d-%H-%M)
32     pg_dump --user=$PLC_DB_USER planetlab4 > $DUMP4.sql
33
34     # check if planetlab5 exists
35     if check_for_database planetlab5 ; then
36         echo 'WARNING: found an existing DB named planetlab5'
37         i=0
38         while true; do
39             i=$(($i+1))
40             bkname=$(printf planetlab5-%03d $i)
41             if check_for_database $bkname ; then
42                 echo "$bkname already exists - skipping"
43             else
44                 echo "Renaming planetab5 into $bkname"
45                 psql --user=$PLC_DB_USER -c "ALTER DATABASE planetlab5 RENAME TO $bkname"
46                 echo "Done"
47             fi
48         done
49     fi
50     if check_for_database planetlab5 ; then
51         echo ERROR : FOUND planetlab5 - exiting
52         exit 1
53     else
54         echo OK : db planetlab5 NOT FOUND 
55     fi
56
57     # create it
58     createdb --user=postgres --encoding=UNICODE --owner=$PLC_DB_USER planetlab5
59     # populate it
60     psql --user=$PLC_DB_USER planetlab5 < $DUMP4.sql
61
62     # run coarse-grain script
63     migration_script | psql --user=$PLC_DB_USER planetlab5 
64     
65 }
66
67
68 function migration_script () {
69
70     cat <<EOF
71
72 -- $Id$
73 --
74 -- this is the script to migrate from 4.2 to 5.0
75 --
76
77 ----------------------------------------
78 -- rename nodenetwork into interface
79 ----------------------------------------
80
81 ALTER TABLE nodenetworks RENAME TO interfaces;
82 ALTER TABLE interfaces RENAME COLUMN nodenetwork_id TO interface_id;
83
84 ALTER INDEX nodenetworks_node_id_idx RENAME TO interfaces_node_id_idx;
85
86 ALTER TABLE nodenetwork_setting_types RENAME TO interface_setting_types;
87 ALTER TABLE interface_setting_types RENAME COLUMN nodenetwork_setting_type_id TO interface_setting_type_id;
88
89 ALTER TABLE nodenetwork_setting RENAME TO interface_setting;
90
91 -- views
92 ALTER TABLE nodenetworks_ordered RENAME TO interfaces_ordered;
93 ALTER TABLE interfaces_ordered RENAME COLUMN nodenetwork_id TO interface_id;
94
95 ALTER TABLE node_nodenetworks RENAME TO node_interfaces;
96 ALTER TABLE node_interfaces RENAME COLUMN nodenetwork_ids TO interface_ids;
97
98 ALTER TABLE nodenetwork_settings RENAME TO interface_settings;
99 ALTER TABLE interface_settings RENAME COLUMN nodenetwork_id TO interface_id;
100 ALTER TABLE interface_settings RENAME COLUMN nodenetwork_setting_ids TO setting_ids;
101
102 ALTER TABLE view_nodenetwork_settings RENAME TO view_interface_settings;
103 ALTER TABLE view_interface_settings RENAME COLUMN nodenetwork_setting_id TO interface_setting_id;
104 ALTER TABLE view_interface_settings RENAME COLUMN nodenetwork_id TO interface_id;
105 ALTER TABLE view_interface_settings RENAME COLUMN nodenetwork_setting_type_id TO interface_setting_type_id;
106
107 ALTER TABLE view_nodenetworks RENAME TO view_interfaces;
108 ALTER TABLE view_interfaces RENAME COLUMN nodenetwork_id TO interface_id;
109 ALTER TABLE view_interfaces RENAME COLUMN nodenetwork_setting_ids TO setting_ids;
110
111 ALTER TABLE view_nodes RENAME COLUMN nodenetwork_ids TO interface_ids;
112
113 ----------------------------------------
114 -- node tags
115 ----------------------------------------
116 CREATE TABLE node_tag_types (
117
118     node_tag_type_id serial PRIMARY KEY,        -- ID
119     name text UNIQUE NOT NULL,                  -- Tag Name
120     description text,                           -- Optional Description
121     category text NOT NULL,                     -- Free text for grouping tags together
122     min_role_id integer REFERENCES roles        -- set minimal role required
123 ) WITH OIDS;
124
125 CREATE TABLE node_tag (
126     node_tag_id serial PRIMARY KEY,             -- ID
127     node_id integer REFERENCES nodes NOT NULL,  -- node id
128     node_tag_type_id integer REFERENCES node_tag_types,
129                                                 -- tag type id
130     value text                                  -- value attached
131 ) WITH OIDS;
132
133 ---------- related views
134 CREATE OR REPLACE VIEW node_tags AS
135 SELECT node_id,
136 array_accum(node_tag_id) AS tag_ids
137 FROM node_tag
138 GROUP BY node_id;
139
140 CREATE OR REPLACE VIEW view_node_tags AS
141 SELECT
142 node_tag.node_tag_id,
143 node_tag.node_id,
144 node_tag_types.node_tag_type_id,
145 node_tag_types.name,
146 node_tag_types.description,
147 node_tag_types.category,
148 node_tag_types.min_role_id,
149 node_tag.value
150 FROM node_tag 
151 INNER JOIN node_tag_types USING (node_tag_type_id);
152
153 DROP VIEW view_nodes;
154 CREATE OR REPLACE VIEW view_nodes AS
155 SELECT
156 nodes.node_id,
157 nodes.hostname,
158 nodes.site_id,
159 nodes.boot_state,
160 nodes.deleted,
161 nodes.model,
162 nodes.boot_nonce,
163 nodes.version,
164 nodes.ssh_rsa_key,
165 nodes.key,
166 CAST(date_part('epoch', nodes.date_created) AS bigint) AS date_created,
167 CAST(date_part('epoch', nodes.last_updated) AS bigint) AS last_updated,
168 CAST(date_part('epoch', nodes.last_contact) AS bigint) AS last_contact,  
169 peer_node.peer_id,
170 peer_node.peer_node_id,
171 COALESCE((SELECT interface_ids FROM node_interfaces WHERE node_interfaces.node_id = nodes.node_id), '{}') AS interface_ids,
172 COALESCE((SELECT nodegroup_ids FROM node_nodegroups WHERE node_nodegroups.node_id = nodes.node_id), '{}') AS nodegroup_ids,
173 COALESCE((SELECT slice_ids FROM node_slices WHERE node_slices.node_id = nodes.node_id), '{}') AS slice_ids,
174 COALESCE((SELECT slice_ids_whitelist FROM node_slices_whitelist WHERE node_slices_whitelist.node_id = nodes.node_id), '{}') AS slice_ids_whitelist,
175 COALESCE((SELECT pcu_ids FROM node_pcus WHERE node_pcus.node_id = nodes.node_id), '{}') AS pcu_ids,
176 COALESCE((SELECT ports FROM node_pcus WHERE node_pcus.node_id = nodes.node_id), '{}') AS ports,
177 COALESCE((SELECT conf_file_ids FROM node_conf_files WHERE node_conf_files.node_id = nodes.node_id), '{}') AS conf_file_ids,
178 COALESCE((SELECT tag_ids FROM node_tags WHERE node_tags.node_id = nodes.node_id), '{}') AS tag_ids,
179 node_session.session_id AS session
180 FROM nodes
181 LEFT JOIN peer_node USING (node_id)
182 LEFT JOIN node_session USING (node_id);
183
184 ----------------------------------------
185 -- nodegroups
186 -- xxx - todo 
187 -- a more usable migration script would need to capture more data
188 ----------------------------------------
189 DROP TABLE IF EXISTS nodegroups CASCADE;
190
191 -- Node groups
192 CREATE TABLE nodegroups (
193     nodegroup_id serial PRIMARY KEY,                    -- Group identifier
194     name text UNIQUE NOT NULL,                          -- Group name
195     node_tag_type_id integer REFERENCES node_tag_types, -- node is in nodegroup if it has this tag defined
196     value text                                          -- with value 'value'
197 ) WITH OIDS;
198
199 CREATE OR REPLACE VIEW nodegroup_node AS
200 SELECT nodegroup_id, node_id 
201 FROM node_tag_types 
202 JOIN node_tag 
203 USING (node_tag_type_id) 
204 JOIN nodegroups 
205 USING (node_tag_type_id,value);
206
207 CREATE OR REPLACE VIEW nodegroup_nodes AS
208 SELECT nodegroup_id,
209 array_accum(node_id) AS node_ids
210 FROM nodegroup_node
211 GROUP BY nodegroup_id;
212
213 -- Node groups that each node is a member of
214 CREATE OR REPLACE VIEW node_nodegroups AS
215 SELECT node_id,
216 array_accum(nodegroup_id) AS nodegroup_ids
217 FROM nodegroup_node
218 GROUP BY node_id;
219
220 ----------------------------------------
221 -- update versioning
222 ----------------------------------------
223 UPDATE plc_db_version SET version=5, subversion=0;
224
225 EOF
226
227 }