Updated 'Verify accout' email message template
[myplc.git] / db-config
1 #!/usr/bin/env /usr/bin/plcsh
2 #
3 # Bootstraps the PLC database with a default administrator account and
4 # a default site, defines default slice attribute types, and
5 # creates/updates default system slices.
6 #
7 # Mark Huang <mlhuang@cs.princeton.edu>
8 # Copyright (C) 2006 The Trustees of Princeton University
9 #
10 # $Id$
11 # $HeadURL$
12
13 from plc_config import PLCConfiguration
14 import sys
15
16 def main():
17     cfg = PLCConfiguration()
18     cfg.load()
19     variables = cfg.variables()
20
21     # Load variables into dictionaries
22     for category_id, (category, variablelist) in variables.iteritems():
23         globals()[category_id] = dict(zip(variablelist.keys(),
24                                        [variable['value'] for variable in variablelist.values()]))
25
26     # Create/update the default administrator account (should be
27     # person_id 2).
28     admin = { 'person_id': 2,
29               'first_name': "Default",
30               'last_name': "Administrator",
31               'email': plc['root_user'],
32               'password': plc['root_password'] }
33     persons = GetPersons([admin['person_id']])
34     if not persons:
35         person_id = AddPerson(admin)
36         if person_id != admin['person_id']:
37             # Huh? Someone deleted the account manually from the database.
38             DeletePerson(person_id)
39             raise Exception, "Someone deleted the \"%s %s\" account from the database!" % \
40                   (admin['first_name'], admin['last_name'])
41         UpdatePerson(person_id, { 'enabled': True })
42     else:
43         person_id = persons[0]['person_id']
44         UpdatePerson(person_id, admin)
45
46     # Create/update the default site (should be site_id 1)
47     if plc_www['port'] == '80':
48         url = "http://" + plc_www['host'] + "/"
49     elif plc_www['port'] == '443':
50         url = "https://" + plc_www['host'] + "/"
51     else:
52         url = "http://" + plc_www['host'] + ":" + plc_www['port'] + "/"
53     site = { 'site_id': 1,
54              'name': plc['name'] + " Central",
55              'abbreviated_name': plc['name'],
56              'login_base': plc['slice_prefix'],
57              'is_public': False,
58              'url': url,
59              'max_slices': 100 }
60
61     sites = GetSites([site['site_id']])
62     if not sites:
63         site_id = AddSite(site['name'], site['abbreviated_name'], site['login_base'], site)
64         if site_id != site['site_id']:
65             DeleteSite(site_id)
66             raise Exception, "Someone deleted the \"%s\" site from the database!" % \
67                   site['name']
68         sites = [site]
69
70     # Must call UpdateSite() even after AddSite() to update max_slices
71     site_id = sites[0]['site_id']
72     UpdateSite(site_id, site)
73
74     # The default administrator account must be associated with a site
75     # in order to login.
76     AddPersonToSite(admin['person_id'], site['site_id'])
77     SetPersonPrimarySite(admin['person_id'], site['site_id'])
78
79     # Grant admin and PI roles to the default administrator account
80     AddRoleToPerson(10, admin['person_id'])
81     AddRoleToPerson(20, admin['person_id'])
82
83     #################### node tags
84     default_node_types = [
85         { 'tagname' : 'arch',
86           'description' : 'architecture name',
87           'category' : 'node/config', 
88           'min_role_id' : 40} ,
89         { 'tagname' : 'pldistro',
90           'description' : 'PlanetLab distribution',
91           'category' : 'node/config', 
92           'min_role_id' : 10} ,
93         { 'tagname' : 'deployment',
94           'description' : 'typically "alpha", "beta", or "production"',
95           'category' : 'node/operation', 
96           'min_role_id' : 10} ,
97         ]
98
99     #################### interface settings
100
101     # Setup default slice attribute types
102     default_setting_types = [
103         {'category' : "interface/general",
104          'tagname' : "ifname",
105          'description': "Set interface name, instead of eth0 or the like",
106          'min_role_id' : 40},
107         {'category' : "interface/multihome",
108          'tagname' : "alias",
109          'description': "Specifies that the network is used for multihoming",
110          'min_role_id' : 40},
111
112         {'category' : "interface/hidden",
113          'tagname' : "backdoor",
114          'description': "For testing new settings",
115          'min_role_id' : 10},
116         ] + [
117         { 'category' : "interface/wifi",
118           'tagname' : x,
119           'description' : "802.11 %s -- see %s"%(y,z),
120           'min_role_id' : 40 } for (x,y,z) in [
121             ("mode","Mode","iwconfig"),
122             ("essid","ESSID","iwconfig"),
123             ("nw","Network Id","iwconfig"),
124             ("freq","Frequency","iwconfig"),
125             ("channel","Channel","iwconfig"),
126             ("sens","sensitivity threshold","iwconfig"),
127             ("rate","Rate","iwconfig"),
128             ("key","key","iwconfig key"),
129             ("key1","key1","iwconfig key [1]"),
130             ("key2","key2","iwconfig key [2]"),
131             ("key3","key3","iwconfig key [3]"),
132             ("key4","key4","iwconfig key [4]"),
133             ("securitymode","Security mode","iwconfig enc"),
134             ("iwconfig","Additional parameters to iwconfig","ifup-wireless"),
135             ("iwpriv","Additional parameters to iwpriv","ifup-wireless"),
136             ]
137         ]
138
139     #################### slice attributes
140
141     # Setup default slice attribute types
142     default_attribute_types = [
143         # Slice type (only vserver is supported)
144         {'tagname': "type",
145          'description': "Type of slice (e.g. vserver)",
146          'category' : 'slice/general',
147          'min_role_id': 20},
148
149         # System slice
150         {'tagname': "system",
151          'description': "Is a default system slice (1) or not (0 or unset)",
152          'category' : 'slice/general',
153          'min_role_id': 10},
154
155         # Slice enabled (1) or suspended (0)
156         {'tagname': "enabled",
157          'description': "Slice enabled (1 or unset) or suspended (0)",
158          'category' : 'slice/general',
159          'min_role_id': 10},
160
161         # Slice reference image
162         {'tagname': "vref",
163          'description': "Reference image",
164          'category' : 'slice/config',
165          'min_role_id': 30},
166
167         # Slice initialization script
168         {'tagname': "initscript",
169          'description': "Slice initialization script",
170          'category' : 'slice/config',
171          'min_role_id': 10},
172
173         # CPU share
174         {'tagname': "cpu_pct",
175          'description': "Reserved CPU percent",
176          'category' : 'slice/rspec',
177          'min_role_id': 10},
178         {'tagname': "cpu_share",
179          'description': "Number of CPU shares",
180          'category' : 'slice/rspec',
181          'min_role_id': 10},
182
183         # Bandwidth limits
184         {'tagname': "net_min_rate",
185          'description': "Minimum bandwidth (kbps)",
186          'category' : 'slice/rspec',
187          'min_role_id': 10},
188         {'tagname': "net_max_rate",
189          'description': "Maximum bandwidth (kbps)",
190          'category' : 'slice/rspec',
191          'min_role_id': 10},
192         {'tagname': "net_i2_min_rate",
193          'description': "Minimum bandwidth over I2 routes (kbps)",
194          'category' : 'slice/rspec',
195          'min_role_id': 10},
196         {'tagname': "net_i2_max_rate",
197          'description': "Maximum bandwidth over I2 routes (kbps)",
198          'category' : 'slice/rspec',
199          'min_role_id': 10},
200         {'tagname': "net_max_kbyte",
201          'description': "Maximum daily network Tx KByte limit.",
202          'category' : 'slice/rspec',
203          'min_role_id': 10},
204         {'tagname': "net_thresh_kbyte",
205          'description': "KByte limit before warning and throttling.",
206          'category' : 'slice/rspec',
207          'min_role_id': 10},
208         {'tagname': "net_i2_max_kbyte",
209          'description': "Maximum daily network Tx KByte limit to I2 hosts.",
210          'category' : 'slice/rspec',
211          'min_role_id': 10},
212         {'tagname': "net_i2_thresh_kbyte",
213          'description': "KByte limit to I2 hosts before warning and throttling.",
214          'category' : 'slice/rspec',
215          'min_role_id': 10},
216         {'tagname': "net_share",
217          'description': "Number of bandwidth shares",
218          'category' : 'slice/rspec',
219          'min_role_id': 10},
220         {'tagname': "net_i2_share",
221          'description': "Number of bandwidth shares over I2 routes",
222          'category' : 'slice/rspec',
223          'min_role_id': 10},
224  
225         # Disk quota
226         {'tagname': "disk_max",
227          'description': "Disk quota (1k disk blocks)",
228          'category' : 'slice/rspec',
229          'min_role_id': 10},
230
231         # Proper operations
232         {'tagname': "proper_op",
233          'description': "Proper operation (e.g. bind_socket)",
234          'category' : 'slice/rspec',
235          'min_role_id': 10},
236
237         # VServer capabilities 
238         {'tagname': "capabilities",
239          'description': "VServer bcapabilities (separate by commas)",
240          'category' : 'slice/rspec',
241          'min_role_id': 10},
242
243                 # Vsys
244         {'tagname': "vsys",
245          'description': "Bind vsys script fd's to a slice's vsys directory.",
246          'category' : 'slice/rspec',
247          'min_role_id': 10},
248
249         # CoDemux
250         {'tagname': "codemux",
251          'description': "Demux HTTP between slices using localhost ports. Value in the form 'host, localhost port'.",
252          'category' : 'slice/rspec',
253          'min_role_id': 10},
254
255         ]
256
257     # Get list of existing tag types
258     known_tag_types = [tag_type['tagname'] for tag_type in GetTagTypes()]
259
260     all_default_types = default_node_types + default_setting_types + default_attribute_types
261     # Create/update default slice tag types
262     for default_tag_type in all_default_types:
263         if default_tag_type['tagname'] not in known_tag_types:
264             AddTagType(default_tag_type)
265         else:
266             UpdateTagType(default_tag_type['tagname'], default_tag_type)
267
268     #################### conf files
269
270     # Setup default PlanetLabConf entries
271     default_conf_files = [
272         # NTP configuration
273         {'enabled': True,
274          'source': 'PlanetLabConf/ntp.conf.php',
275          'dest': '/etc/ntp.conf',
276          'file_permissions': '644',
277          'file_owner': 'root',
278          'file_group': 'root',
279          'preinstall_cmd': '',
280          'postinstall_cmd': '/etc/rc.d/init.d/ntpd restart',
281          'error_cmd': '',
282          'ignore_cmd_errors': False,
283          'always_update': False},
284         {'enabled': True,
285          'source': 'PlanetLabConf/ntp/step-tickers.php',
286          'dest': '/etc/ntp/step-tickers',
287          'file_permissions': '644',
288          'file_owner': 'root',
289          'file_group': 'root',
290          'preinstall_cmd': '',
291          'postinstall_cmd': '/etc/rc.d/init.d/ntpd restart',
292          'error_cmd': '',
293          'ignore_cmd_errors': False,
294          'always_update': False},
295
296         # SSH server configuration
297         {'enabled': True,
298          'source': 'PlanetLabConf/sshd_config',
299          'dest': '/etc/ssh/sshd_config',
300          'file_permissions': '600',
301          'file_owner': 'root',
302          'file_group': 'root',
303          'preinstall_cmd': '',
304          'postinstall_cmd': '/etc/init.d/sshd restart',
305          'error_cmd': '',
306          'ignore_cmd_errors': False,
307          'always_update': False},
308
309         # Administrative SSH keys
310         {'enabled': True,
311          'source': 'PlanetLabConf/keys.php?root',
312          'dest': '/root/.ssh/authorized_keys',
313          'file_permissions': '644',
314          'file_owner': 'root',
315          'file_group': 'root',
316          'preinstall_cmd': '',
317          'postinstall_cmd': '/bin/chmod 700 /root/.ssh',
318          'error_cmd': '',
319          'ignore_cmd_errors': False,
320          'always_update': False},
321         {'enabled': True,
322          'source': 'PlanetLabConf/keys.php?site_admin',
323          'dest': '/home/site_admin/.ssh/authorized_keys',
324          'file_permissions': '644',
325          'file_owner': 'site_admin',
326          'file_group': 'site_admin',
327          'preinstall_cmd': 'grep -q site_admin /etc/passwd',
328          'postinstall_cmd': '/bin/chmod 700 /home/site_admin/.ssh',
329          'error_cmd': '',
330          'ignore_cmd_errors': False,
331          'always_update': False},
332         # Log rotation configuration
333         {'enabled': True,
334          'source': 'PlanetLabConf/logrotate.conf',
335          'dest': '/etc/logrotate.conf',
336          'file_permissions': '644',
337          'file_owner': 'root',
338          'file_group': 'root',
339          'preinstall_cmd': '',
340          'postinstall_cmd': '',
341          'error_cmd': '',
342          'ignore_cmd_errors': False,
343          'always_update': False},
344
345         # updatedb/locate nightly cron job
346         {'enabled': True,
347          'source': 'PlanetLabConf/slocate.cron',
348          'dest': '/etc/cron.daily/slocate.cron',
349          'file_permissions': '755',
350          'file_owner': 'root',
351          'file_group': 'root',
352          'preinstall_cmd': '',
353          'postinstall_cmd': '',
354          'error_cmd': '',
355          'ignore_cmd_errors': False,
356          'always_update': False},
357
358         # YUM configuration
359         {'enabled': True,
360          'source': 'yum/myplc.repo.php?gpgcheck=1',
361          'dest': '/etc/yum.myplc.d/myplc.repo',
362          'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root',
363          'preinstall_cmd': '', 'postinstall_cmd': '', 'error_cmd': '',
364          'ignore_cmd_errors': False,
365          'always_update': False},
366         {'enabled': True,
367          'source': 'yum/yum.conf',
368          'dest': '/etc/yum.conf',
369          'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root',
370          'preinstall_cmd': '', 'postinstall_cmd': '', 'error_cmd': '',
371          'ignore_cmd_errors': False,
372          'always_update': False},
373         {'enabled': True,
374          'source': 'yum/stock.repo',
375          'dest': '/etc/yum.myplc.d/stock.repo',
376          'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root',
377          'preinstall_cmd': '', 'postinstall_cmd': '', 'error_cmd': '',
378          'ignore_cmd_errors': False,
379          'always_update': False},
380
381         {'enabled': True,
382          'source': 'PlanetLabConf/delete-rpm-list-production',
383          'dest': '/etc/planetlab/delete-rpm-list',
384          'file_permissions': '644',
385          'file_owner': 'root',
386          'file_group': 'root',
387          'preinstall_cmd': '',
388          'postinstall_cmd': '',
389          'error_cmd': '',
390          'ignore_cmd_errors': False,
391          'always_update': False},
392
393         # PLC configuration
394         {'enabled': True,
395          'source': 'PlanetLabConf/get_plc_config.php',
396          'dest': '/etc/planetlab/plc_config',
397          'file_permissions': '644',
398          'file_owner': 'root',
399          'file_group': 'root',
400          'preinstall_cmd': '',
401          'postinstall_cmd': '',
402          'error_cmd': '',
403          'ignore_cmd_errors': False,
404          'always_update': False},
405         {'enabled': True,
406          'source': 'PlanetLabConf/get_plc_config.php?python',
407          'dest': '/etc/planetlab/plc_config.py',
408          'file_permissions': '644',
409          'file_owner': 'root',
410          'file_group': 'root',
411          'preinstall_cmd': '',
412          'postinstall_cmd': '',
413          'error_cmd': '',
414          'ignore_cmd_errors': False,
415          'always_update': False},
416         {'enabled': True,
417          'source': 'PlanetLabConf/get_plc_config.php?perl',
418          'dest': '/etc/planetlab/plc_config.pl',
419          'file_permissions': '644',
420          'file_owner': 'root',
421          'file_group': 'root',
422          'preinstall_cmd': '',
423          'postinstall_cmd': '',
424          'error_cmd': '',
425          'ignore_cmd_errors': False,
426          'always_update': False},
427         {'enabled': True,
428          'source': 'PlanetLabConf/get_plc_config.php?php',
429          'dest': '/etc/planetlab/php/plc_config.php',
430          'file_permissions': '644',
431          'file_owner': 'root',
432          'file_group': 'root',
433          'preinstall_cmd': '',
434          'postinstall_cmd': '',
435          'error_cmd': '',
436          'ignore_cmd_errors': False,
437          'always_update': False},
438
439         # XXX Required for old Node Manager
440         # Proper configuration
441         {'enabled': True,
442          'source': 'PlanetLabConf/propd.conf',
443          'dest': '/etc/proper/propd.conf',
444          'file_permissions': '644',
445          'file_owner': 'root',
446          'file_group': 'root',
447          'preinstall_cmd': '',
448          'postinstall_cmd': '/etc/init.d/proper restart',
449          'error_cmd': '',
450          'ignore_cmd_errors': True,
451          'always_update': False},
452
453         # XXX Required for old Node Manager
454         # Bandwidth cap
455         {'enabled': True,
456          'source': 'PlanetLabConf/bwlimit.php',
457          'dest': '/etc/planetlab/bwcap',
458          'file_permissions': '644',
459          'file_owner': 'root',
460          'file_group': 'root',
461          'preinstall_cmd': '',
462          'postinstall_cmd': '',
463          'error_cmd': '',
464          'ignore_cmd_errors': True,
465          'always_update': False},
466
467         # Proxy ARP setup
468         {'enabled': True,
469          'source': 'PlanetLabConf/proxies.php',
470          'dest': '/etc/planetlab/proxies',
471          'file_permissions': '644',
472          'file_owner': 'root',
473          'file_group': 'root',
474          'preinstall_cmd': '',
475          'postinstall_cmd': '',
476          'error_cmd': '',
477          'ignore_cmd_errors': False,
478          'always_update': False},
479
480         # Firewall configuration
481         {'enabled': True,
482          'source': 'PlanetLabConf/blacklist.php',
483          'dest': '/etc/planetlab/blacklist',
484          'file_permissions': '600',
485          'file_owner': 'root',
486          'file_group': 'root',
487          'preinstall_cmd': '',
488          'postinstall_cmd': '/sbin/iptables-restore --noflush < /etc/planetlab/blacklist',
489          'error_cmd': '',
490          'ignore_cmd_errors': True,
491          'always_update': False},
492
493         # /etc/issue
494         {'enabled': True,
495          'source': 'PlanetLabConf/issue.php',
496          'dest': '/etc/issue',
497          'file_permissions': '644',
498          'file_owner': 'root',
499          'file_group': 'root',
500          'preinstall_cmd': '',
501          'postinstall_cmd': '',
502          'error_cmd': '',
503          'ignore_cmd_errors': False,
504          'always_update': False},
505
506         # Kernel parameters
507         {'enabled': True,
508          'source': 'PlanetLabConf/sysctl.php',
509          'dest': '/etc/sysctl.conf',
510          'file_permissions': '644',
511          'file_owner': 'root',
512          'file_group': 'root',
513          'preinstall_cmd': '',
514          'postinstall_cmd': '/sbin/sysctl -e -p /etc/sysctl.conf',
515          'error_cmd': '',
516          'ignore_cmd_errors': False,
517          'always_update': False},
518
519         # Sendmail configuration
520         {'enabled': True,
521          'source': 'PlanetLabConf/sendmail.mc',
522          'dest': '/etc/mail/sendmail.mc',
523          'file_permissions': '644',
524          'file_owner': 'root',
525          'file_group': 'root',
526          'preinstall_cmd': '',
527          'postinstall_cmd': '',
528          'error_cmd': '',
529          'ignore_cmd_errors': False,
530          'always_update': False},
531         {'enabled': True,
532          'source': 'PlanetLabConf/sendmail.cf',
533          'dest': '/etc/mail/sendmail.cf',
534          'file_permissions': '644',
535          'file_owner': 'root',
536          'file_group': 'root',
537          'preinstall_cmd': '',
538          'postinstall_cmd': 'service sendmail restart',
539          'error_cmd': '',
540          'ignore_cmd_errors': False,
541          'always_update': False},
542
543         # GPG signing keys
544         {'enabled': True,
545          'source': 'PlanetLabConf/RPM-GPG-KEY-fedora',
546          'dest': '/etc/pki/rpm-gpg/RPM-GPG-KEY-fedora',
547          'file_permissions': '644',
548          'file_owner': 'root',
549          'file_group': 'root',
550          'preinstall_cmd': '',
551          'postinstall_cmd': 'rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-fedora',
552          'error_cmd': '',
553          'ignore_cmd_errors': False,
554          'always_update': False},
555         {'enabled': True,
556          'source': 'PlanetLabConf/get_gpg_key.php',
557          'dest': '/etc/pki/rpm-gpg/RPM-GPG-KEY-planetlab',
558          'file_permissions': '644',
559          'file_owner': 'root',
560          'file_group': 'root',
561          'preinstall_cmd': '',
562          'postinstall_cmd': 'rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-planetlab',
563          'error_cmd': '',
564          'ignore_cmd_errors': False,
565          'always_update': False},
566
567         # Ping of death configuration
568         # the 'restart' postcommand doesn't work, b/c the pod script doesn't support it.
569         {'enabled': True,
570          'source': 'PlanetLabConf/ipod.conf.php',
571          'dest': '/etc/ipod.conf',
572          'file_permissions': '644',
573          'file_owner': 'root',
574          'file_group': 'root',
575          'preinstall_cmd': '',
576          'postinstall_cmd': '/etc/init.d/pod start',
577          'error_cmd': '',
578          'ignore_cmd_errors': False,
579          'always_update': False},
580
581         # sudo configuration
582         {'enabled': True,
583          'source': 'PlanetLabConf/sudoers.php',
584          'dest': '/etc/sudoers',
585          'file_permissions': '440',
586          'file_owner': 'root',
587          'file_group': 'root',
588          'preinstall_cmd': '',
589          'postinstall_cmd': '/usr/sbin/visudo -c',
590          'error_cmd': '',
591          'ignore_cmd_errors': False,
592          'always_update': False}
593         ]
594
595     # Get list of existing (enabled, global) files
596     conf_files = GetConfFiles()
597     conf_files = filter(lambda conf_file: conf_file['enabled'] and \
598                                           not conf_file['node_ids'] and \
599                                           not conf_file['nodegroup_ids'],
600                         conf_files)
601     dests = [conf_file['dest'] for conf_file in conf_files]
602     conf_files = dict(zip(dests, conf_files))
603
604     # Create/update default PlanetLabConf entries
605     for default_conf_file in default_conf_files:
606         if default_conf_file['dest'] not in dests:
607             AddConfFile(default_conf_file)
608         else:
609             conf_file = conf_files[default_conf_file['dest']]
610             UpdateConfFile(conf_file['conf_file_id'], default_conf_file)
611
612
613     #################### initscripts
614
615     # Default Initscripts
616     default_initscripts = []
617
618     # Find initscripts and add them to the db
619     for (root, dirs, files) in os.walk("/etc/plc_sliceinitscripts"):
620         for f in files:
621             # Read the file
622             file = open(root + "/" + f, "ro")
623             default_initscripts.append({"name": plc['slice_prefix'] + "_" + f,
624                                         "enabled": True,
625                                         "script": file.read().replace("@SITE@", url).replace("@PREFIX@", plc['slice_prefix'])})
626             file.close()
627
628     # Get list of existing initscripts
629     oldinitscripts = GetInitScripts()
630     oldinitscripts = [script['name'] for script in oldinitscripts]
631
632     for initscript in default_initscripts:
633         if initscript['name'] not in oldinitscripts:  AddInitScript(initscript)
634
635     # Create/update system slices
636     default_slices = [
637          # PlanetFlow
638         {'name': plc['slice_prefix'] + "_netflow",
639          'description': "PlanetFlow Traffic Auditing Service.  Logs, captured in the root context using fprobe-ulogd, are stored in a directory in the root context which is bind mounted to the planetflow slice.  The Planetflow Central service then periodically rsyncs these logs from the planetflow slice for aggregation.",
640          'url': url,
641          'instantiation': "plc-instantiated",
642          # Renew forever (minus one day, work around date conversion weirdness)
643          'expires': 0x7fffffff - (60 * 60 * 24),
644          'attributes': [('system', "1"),
645                         ('vref', "planetflow"),
646                                                 ('vsys', "pfmount")]},
647           # Sirius
648         {'name': plc['slice_prefix'] + "_sirius",
649          'description': 'The Sirius Calendar Service.\n\nSirius provides system-wide reservations of 25% CPU and 2Mb/s outgoing\nbandwidth.  Sign up for hour-long slots using the Web GUI at the\nPlanetLab website.\n\nThis slice should not generate traffic external to PlanetLab.\n',
650          'url': url + "db/sirius/index.php",
651          'instantiation': "plc-instantiated",
652          # Renew forever (minus one day, work around date conversion weirdness)
653          'expires': 0x7fffffff - (60 * 60 * 24),
654          'attributes': [('system', "1"),
655                         ('net_min_rate', "2000"),
656                         ('cpu_pct', "25"),
657                         ('initscript', plc['slice_prefix'] + "_sirius")]}
658         ]
659     
660     for default_slice in default_slices:
661         slices = GetSlices([default_slice['name']])
662         if slices:
663             slice = slices[0]
664             UpdateSlice(slice['slice_id'], default_slice)
665         else:
666             AddSlice(default_slice)
667             slice = GetSlices([default_slice['name']])[0]
668
669         # Create/update all attributes
670         slice_attributes = []
671         if slice['slice_attribute_ids']:
672             # Delete unknown attributes
673             for slice_attribute in GetSliceAttributes(slice['slice_attribute_ids']):
674                 if (slice_attribute['name'], slice_attribute['value']) \
675                    not in default_slice['attributes']:
676                     DeleteSliceAttribute(slice_attribute['slice_attribute_id'])
677                 else:
678                     slice_attributes.append((slice_attribute['name'], slice_attribute['value']))
679
680         for (name, value) in default_slice['attributes']:
681             if (name, value) not in slice_attributes:
682                 AddSliceAttribute(slice['name'], name, value)
683
684     
685     #################### body for messages
686
687     installfailed = """
688 Once the node meets these requirements, please reinitiate the install
689 by visiting:
690
691 https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/nodes/?id=%(node_id)d
692
693 Update the BootState to 'Reinstall', then reboot the node.
694
695 If you have already performed this step and are still receiving this
696 message, please reply so that we may investigate the problem.
697 """
698
699     # Load default message templates
700     message_templates = [
701         {'message_id': 'Verify account',
702          'subject': "Verify account registration",
703          'template': """
704 Please verify that you registered for a %(PLC_NAME)s account with the
705 username %(email)s by visiting:
706
707 https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/persons/register.php?id=%(person_id)d&key=%(verification_key)s
708
709 You must wait for this account to be approved before you can begin using it, please be patient.
710
711 If you did not register for a %(PLC_NAME)s account, please ignore this
712 message, or contact %(PLC_NAME)s Support <%(PLC_MAIL_SUPPORT_ADDRESS)s>.
713 """
714          },
715
716         {'message_id': 'New PI account',
717          'subject': "New PI account registration from %(first_name)s %(last_name)s <%(email)s> at %(site_name)s",
718          'template': """
719 %(first_name)s %(last_name)s <%(email)s> has signed up for a new
720 %(PLC_NAME)s account at %(site_name)s and has requested a PI role. PIs
721 are responsible for enabling user accounts, creating slices, and
722 ensuring that all users abide by the %(PLC_NAME)s Acceptable Use
723 Policy.
724
725 Only %(PLC_NAME)s administrators may enable new PI accounts. If you
726 are a PI at %(site_name)s, please respond and indicate whether this
727 registration is acceptable.
728
729 To view the request, visit:
730
731 https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/persons/index.php?id=%(person_id)d
732 """
733          },
734
735         {'message_id': 'New account',
736          'subject': "New account registration from %(first_name)s %(last_name)s <%(email)s> at %(site_name)s",
737          'template': """
738 %(first_name)s %(last_name)s <%(email)s> has signed up for a new
739 %(PLC_NAME)s account at %(site_name)s and has requested the following
740 roles: %(roles)s.
741
742 To deny the request or enable the account, visit:
743
744 https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/persons/index.php?id=%(person_id)d
745 """
746          },
747
748         {'message_id': 'Password reset requested',
749          'subject': "Password reset requested",
750          'template': """
751 Someone has requested that the password of your %(PLC_NAME)s account
752 %(email)s be reset. If this person was you, you may continue with the
753 reset by visiting:
754
755 https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/persons/reset_password.php?id=%(person_id)d&key=%(verification_key)s
756
757 If you did not request that your password be reset, please contact
758 %(PLC_NAME)s Support <%(PLC_MAIL_SUPPORT_ADDRESS)s>. Do not quote or
759 otherwise include any of this text in any correspondence.
760 """
761          },
762
763         {'message_id': 'Password reset',
764          'subject': "Password reset",
765          'template': """
766 The password of your %(PLC_NAME)s account %(email)s has been
767 temporarily reset to:
768
769 %(password)s
770
771 Please change it at as soon as possible by visiting:
772
773 https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/persons/index.php?id=%(person_id)d
774
775 If you did not request that your password be reset, please contact
776 %(PLC_NAME)s Support <%(PLC_MAIL_SUPPORT_ADDRESS)s>. Do not quote or
777 otherwise include any of this text in any correspondence.
778 """
779          },
780
781         # Boot Manager messages
782         {'message_id': "installfinished",
783          'subject': "%(hostname)s completed installation",
784          'template': """
785 %(hostname)s just completed installation.
786
787 The node should be usable in a couple of minutes if installation was
788 successful.
789 """
790          },
791
792         {'message_id': "insufficientdisk",
793          'subject': "%(hostname)s does not have sufficient disk space",
794          'template': """
795 %(hostname)s failed to boot because it does not have sufficent disk
796 space, or because its disk controller was not recognized.
797
798 Please replace the current disk or disk controller or install
799 additional disks to meet the current hardware requirements.
800 """ + installfailed
801          },
802
803         {'message_id': "insufficientmemory",
804          'subject': "%(hostname)s does not have sufficient memory",
805          'template': """
806 %(hostname)s failed to boot because it does not have sufficent
807 memory.
808
809 Please install additional memory to meet the current hardware
810 requirements.
811 """ + installfailed
812          },
813
814         {'message_id': "authfail",
815          'subject': "%(hostname)s failed to authenticate",
816          'template':
817 """
818 %(hostname)s failed to authenticate for the following reason:
819
820 %(fault)s
821
822 The most common reason for authentication failure is that the
823 authentication key stored in the node configuration file, does not
824 match the key on record. 
825
826 There are two possible steps to resolve the problem.
827
828 1. If you have used an All-in-one BootCD that includes the plnode.txt file,
829     then please check your machine for any old boot media, either in the
830     floppy drive, or on a USB stick.  It is likely that an old configuration
831     is being used instead of the new configuration stored on the BootCD.
832 Or, 
833 2. If you are using Generic BootCD image, then regenerate the node 
834     configuration file by visiting:
835
836     https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/nodes/?id=%(node_id)d
837
838     Under 'Download', follow the 'Download plnode.txt file for %(hostname)s'
839     option, and save the downloaded file as plnode.txt on either a floppy 
840     disk or a USB flash drive.  Be sure the 'Boot State' is set to 'Boot', 
841     and, then reboot the node.
842
843 If you have already performed this step and are still receiving this
844 message, please reply so that we can help investigate the problem.
845 """
846          },
847
848         {'message_id': "notinstalled",
849          'subject': "%(hostname)s is not installed",
850          'template':
851 """
852 %(hostname)s failed to boot because it has either never been
853 installed, or the installation is corrupt.
854
855 Please check if the hard drive has failed, and replace it if so. After
856 doing so, visit:
857
858 https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/nodes/?id=%(node_id)d
859
860 Change the 'Boot State' to 'Reinstall', and then reboot the node.
861
862 If you have already performed this step and are still receiving this
863 message, please reply so that we may investigate the problem.
864 """
865          },
866
867         {'message_id': "hostnamenotresolve",
868          'subject': "%(hostname)s does not resolve",
869          'template':
870 """
871 %(hostname)s failed to boot because its hostname does not resolve, or
872 does resolve but does not match its configured IP address.
873
874 Please check the network settings for the node, especially its
875 hostname, IP address, and DNS servers, by visiting:
876
877 https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/nodes/?id=%(node_id)d
878
879 Correct any errors, and change the 'Boot State' to 'Reinstall', and then
880 reboot the node.
881
882 If you have already performed this step and are still receiving this
883 message, please reply so that we may investigate the problem.
884 """
885          },
886
887         # XXX N.B. I don't think these are necessary, since there's no
888         # way that the Boot Manager would even be able to contact the
889         # API to send these messages.
890
891         {'message_id': "noconfig",
892          'subject': "%(hostname)s does not have a configuration file",
893          'template': """
894 %(hostname)s failed to boot because it could not find a PlanetLab
895 configuration file. To create this file, visit:
896
897 https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/nodes/?id=%(node_id)d
898
899 Click the Configuration File link, and save the downloaded file as
900 plnode.txt on either a floppy disk or a USB flash drive.  Change the 
901 'Boot State' to 'Reinstall', and then reboot the node.
902
903 If you have already performed this step and are still receiving this
904 message, please reply so that we may investigate the problem.
905 """
906          },
907
908         {'message_id': "nodetectednetwork",
909          'subject': "%(hostname)s has unsupported network hardware",
910          'template':
911 """
912
913 %(hostname)s failed to boot because it has network hardware that is
914 unsupported by the current production kernel. If it has booted
915 successfully in the past, please try re-installing it by visiting:
916
917 https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/nodes/?id=%(node_id)d
918
919 Change the 'Boot State' to 'Reinstall', and then reboot the node.
920
921 If you have already performed this step and are still receiving this
922 message, please reply so that we may investigate the problem.
923 """
924          },
925         ]
926
927     for template in message_templates:
928         messages = GetMessages([template['message_id']])
929         if not messages:
930             AddMessage(template)
931
932     #################### PCUs
933     
934     ### Setup Initial PCU information
935     pcu_types = [{'model': 'AP79xx',
936           'name': 'APC AP79xx',
937           'pcu_protocol_types': [{ 'port': 80,
938                                   'protocol': 'APC79xxHttp',
939                                   'supported': False},
940                                  { 'port': 23,
941                                   'protocol': 'APC79xx',
942                                   'supported': True},
943                                  { 'port': 22,
944                                   'protocol': 'APC79xx',
945                                   'supported': True}],
946           },
947          {'model': 'Masterswitch',
948           'name': 'APC Masterswitch',
949           'pcu_protocol_types': [{ 'port': 80,
950                                   'protocol': 'APCMasterHttp',
951                                   'supported': False},
952                                  { 'port': 23,
953                                   'protocol': 'APCMaster',
954                                   'supported': True},
955                                  { 'port': 22,
956                                   'protocol': 'APCMaster',
957                                   'supported': True}],
958           },
959          {'model': 'DS4-RPC',
960           'name': 'BayTech DS4-RPC',
961           'pcu_protocol_types': [{ 'port': 80,
962                                   'protocol': 'BayTechHttp',
963                                   'supported': False},
964                                  { 'port': 23,
965                                   'protocol': 'BayTech',
966                                   'supported': True},
967                                  { 'port': 22,
968                                   'protocol': 'BayTech',
969                                   'supported': True}],
970           },
971          {'model': 'IP-41x_IP-81x',
972           'name': 'Dataprobe IP-41x & IP-81x',
973           'pcu_protocol_types': [ { 'port': 23,
974                                   'protocol': 'IPALTelnet',
975                                   'supported': True},
976                                   { 'port': 80,
977                                   'protocol': 'IPALHttp',
978                                   'supported': False}],
979           },
980          {'model': 'DRAC3',
981           'name': 'Dell RAC Version 3',
982           'pcu_protocol_types': [],
983           },
984          {'model': 'DRAC4',
985           'name': 'Dell RAC Version 4',
986           'pcu_protocol_types': [{ 'port': 443,
987                                   'protocol': 'DRACRacAdm',
988                                   'supported': True},
989                                  { 'port': 80,
990                                   'protocol': 'DRACRacAdm',
991                                   'supported': False},
992                                  { 'port': 22,
993                                   'protocol': 'DRAC',
994                                   'supported': True}],
995           },
996          {'model': 'ePowerSwitch',
997           'name': 'ePowerSwitch 1/4/8x',
998           'pcu_protocol_types': [{ 'port': 80,
999                                   'protocol': 'ePowerSwitch',
1000                                   'supported': True}],
1001           },
1002          {'model': 'ilo2',
1003           'name': 'HP iLO2 (Integrated Lights-Out)',
1004           'pcu_protocol_types': [{ 'port': 443,
1005                                   'protocol': 'HPiLOHttps',
1006                                   'supported': True},
1007                                  { 'port': 22,
1008                                   'protocol': 'HPiLO',
1009                                   'supported': True}],
1010           },
1011          {'model': 'ilo1',
1012           'name': 'HP iLO version 1',
1013           'pcu_protocol_types': [],
1014           },
1015          {'model': 'PM211-MIP',
1016           'name': 'Infratec PM221-MIP',
1017           'pcu_protocol_types': [],
1018           },
1019          {'model': 'AMT2.5',
1020           'name': 'Intel AMT v2.5 (Active Management Technology)',
1021           'pcu_protocol_types': [],
1022           },
1023          {'model': 'AMT3.0',
1024           'name': 'Intel AMT v3.0 (Active Management Technology)',
1025           'pcu_protocol_types': [],
1026           },
1027          {'model': 'WTI_IPS-4',
1028           'name': 'Western Telematic (WTI IPS-4)',
1029           'pcu_protocol_types': [],
1030           },
1031          {'model': 'unknown',
1032           'name': 'Unknown Vendor or Model',
1033           'pcu_protocol_types': [{ 'port': 443,
1034                                   'protocol': 'UnknownPCU',
1035                                   'supported': False},
1036                                  { 'port': 80,
1037                                   'protocol': 'UnknownPCU',
1038                                   'supported': False},
1039                                  { 'port': 23,
1040                                   'protocol': 'UnknownPCU',
1041                                   'supported': False},
1042                                  { 'port': 22,
1043                                   'protocol': 'UnknownPCU',
1044                                   'supported': False}],
1045           }]
1046
1047     # Get all model names
1048     pcu_models = [type['model'] for type in GetPCUTypes()]
1049     for type in pcu_types:
1050         protocol_types = type['pcu_protocol_types']
1051         # Take this value out of the struct.
1052         del type['pcu_protocol_types']
1053         if type['model'] not in pcu_models:
1054             # Add the name/model info into DB
1055             id = AddPCUType(type)
1056             # for each protocol, also add this.
1057             for ptype in protocol_types:
1058                 AddPCUProtocolType(id, ptype)
1059
1060         default_boot_states = [
1061                 'boot',
1062                 'failboot',
1063                 'safeboot',
1064                 'install',
1065                 'reinstall',
1066                 'disabled',
1067         ]
1068
1069         current_boot_states = GetBootStates()
1070         for state in default_boot_states:
1071                 if state not in current_boot_states:
1072                         AddBootState(state)
1073
1074         # TODO: Delete old boot states. 
1075         # NOTE: Only do this if all federating peers have the new default boot states above.
1076         #for state in current_boot_states:
1077         #       if state not in default_boot_states:
1078         #               DeleteBootState(state)
1079
1080
1081 if __name__ == '__main__':
1082     main()
1083
1084 # Local variables:
1085 # tab-width: 4
1086 # mode: python
1087 # End: