merged 4.2 + new packaging for nodeconfig/yum
[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 If you did not register for a %(PLC_NAME)s account, please ignore this
710 message, or contact %(PLC_NAME)s Support <%(PLC_MAIL_SUPPORT_ADDRESS)s>.
711 """
712          },
713
714         {'message_id': 'New PI account',
715          'subject': "New PI account registration from %(first_name)s %(last_name)s <%(email)s> at %(site_name)s",
716          'template': """
717 %(first_name)s %(last_name)s <%(email)s> has signed up for a new
718 %(PLC_NAME)s account at %(site_name)s and has requested a PI role. PIs
719 are responsible for enabling user accounts, creating slices, and
720 ensuring that all users abide by the %(PLC_NAME)s Acceptable Use
721 Policy.
722
723 Only %(PLC_NAME)s administrators may enable new PI accounts. If you
724 are a PI at %(site_name)s, please respond and indicate whether this
725 registration is acceptable.
726
727 To view the request, visit:
728
729 https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/persons/index.php?id=%(person_id)d
730 """
731          },
732
733         {'message_id': 'New account',
734          'subject': "New account registration from %(first_name)s %(last_name)s <%(email)s> at %(site_name)s",
735          'template': """
736 %(first_name)s %(last_name)s <%(email)s> has signed up for a new
737 %(PLC_NAME)s account at %(site_name)s and has requested the following
738 roles: %(roles)s.
739
740 To deny the request or enable the account, visit:
741
742 https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/persons/index.php?id=%(person_id)d
743 """
744          },
745
746         {'message_id': 'Password reset requested',
747          'subject': "Password reset requested",
748          'template': """
749 Someone has requested that the password of your %(PLC_NAME)s account
750 %(email)s be reset. If this person was you, you may continue with the
751 reset by visiting:
752
753 https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/persons/reset_password.php?id=%(person_id)d&key=%(verification_key)s
754
755 If you did not request that your password be reset, please contact
756 %(PLC_NAME)s Support <%(PLC_MAIL_SUPPORT_ADDRESS)s>. Do not quote or
757 otherwise include any of this text in any correspondence.
758 """
759          },
760
761         {'message_id': 'Password reset',
762          'subject': "Password reset",
763          'template': """
764 The password of your %(PLC_NAME)s account %(email)s has been
765 temporarily reset to:
766
767 %(password)s
768
769 Please change it at as soon as possible by visiting:
770
771 https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/persons/index.php?id=%(person_id)d
772
773 If you did not request that your password be reset, please contact
774 %(PLC_NAME)s Support <%(PLC_MAIL_SUPPORT_ADDRESS)s>. Do not quote or
775 otherwise include any of this text in any correspondence.
776 """
777          },
778
779         # Boot Manager messages
780         {'message_id': "installfinished",
781          'subject': "%(hostname)s completed installation",
782          'template': """
783 %(hostname)s just completed installation.
784
785 The node should be usable in a couple of minutes if installation was
786 successful.
787 """
788          },
789
790         {'message_id': "insufficientdisk",
791          'subject': "%(hostname)s does not have sufficient disk space",
792          'template': """
793 %(hostname)s failed to boot because it does not have sufficent disk
794 space, or because its disk controller was not recognized.
795
796 Please replace the current disk or disk controller or install
797 additional disks to meet the current hardware requirements.
798 """ + installfailed
799          },
800
801         {'message_id': "insufficientmemory",
802          'subject': "%(hostname)s does not have sufficient memory",
803          'template': """
804 %(hostname)s failed to boot because it does not have sufficent
805 memory.
806
807 Please install additional memory to meet the current hardware
808 requirements.
809 """ + installfailed
810          },
811
812         {'message_id': "authfail",
813          'subject': "%(hostname)s failed to authenticate",
814          'template':
815 """
816 %(hostname)s failed to authenticate for the following reason:
817
818 %(fault)s
819
820 The most common reason for authentication failure is that the
821 authentication key stored in the node configuration file, does not
822 match the key on record. 
823
824 There are two possible steps to resolve the problem.
825
826 1. If you have used an All-in-one BootCD that includes the plnode.txt file,
827     then please check your machine for any old boot media, either in the
828     floppy drive, or on a USB stick.  It is likely that an old configuration
829     is being used instead of the new configuration stored on the BootCD.
830 Or, 
831 2. If you are using Generic BootCD image, then regenerate the node 
832     configuration file by visiting:
833
834     https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/nodes/?id=%(node_id)d
835
836     Under 'Download', follow the 'Download plnode.txt file for %(hostname)s'
837     option, and save the downloaded file as plnode.txt on either a floppy 
838     disk or a USB flash drive.  Be sure the 'Boot State' is set to 'Boot', 
839     and, then reboot the node.
840
841 If you have already performed this step and are still receiving this
842 message, please reply so that we can help investigate the problem.
843 """
844          },
845
846         {'message_id': "notinstalled",
847          'subject': "%(hostname)s is not installed",
848          'template':
849 """
850 %(hostname)s failed to boot because it has either never been
851 installed, or the installation is corrupt.
852
853 Please check if the hard drive has failed, and replace it if so. After
854 doing so, visit:
855
856 https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/nodes/?id=%(node_id)d
857
858 Change the 'Boot State' to 'Reinstall', and then reboot the node.
859
860 If you have already performed this step and are still receiving this
861 message, please reply so that we may investigate the problem.
862 """
863          },
864
865         {'message_id': "hostnamenotresolve",
866          'subject': "%(hostname)s does not resolve",
867          'template':
868 """
869 %(hostname)s failed to boot because its hostname does not resolve, or
870 does resolve but does not match its configured IP address.
871
872 Please check the network settings for the node, especially its
873 hostname, IP address, and DNS servers, by visiting:
874
875 https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/nodes/?id=%(node_id)d
876
877 Correct any errors, and change the 'Boot State' to 'Reinstall', and then
878 reboot the node.
879
880 If you have already performed this step and are still receiving this
881 message, please reply so that we may investigate the problem.
882 """
883          },
884
885         # XXX N.B. I don't think these are necessary, since there's no
886         # way that the Boot Manager would even be able to contact the
887         # API to send these messages.
888
889         {'message_id': "noconfig",
890          'subject': "%(hostname)s does not have a configuration file",
891          'template': """
892 %(hostname)s failed to boot because it could not find a PlanetLab
893 configuration file. To create this file, visit:
894
895 https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/nodes/?id=%(node_id)d
896
897 Click the Configuration File link, and save the downloaded file as
898 plnode.txt on either a floppy disk or a USB flash drive.  Change the 
899 'Boot State' to 'Reinstall', and then reboot the node.
900
901 If you have already performed this step and are still receiving this
902 message, please reply so that we may investigate the problem.
903 """
904          },
905
906         {'message_id': "nodetectednetwork",
907          'subject': "%(hostname)s has unsupported network hardware",
908          'template':
909 """
910
911 %(hostname)s failed to boot because it has network hardware that is
912 unsupported by the current production kernel. If it has booted
913 successfully in the past, please try re-installing it by visiting:
914
915 https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/nodes/?id=%(node_id)d
916
917 Change the 'Boot State' to 'Reinstall', and then reboot the node.
918
919 If you have already performed this step and are still receiving this
920 message, please reply so that we may investigate the problem.
921 """
922          },
923         ]
924
925     for template in message_templates:
926         messages = GetMessages([template['message_id']])
927         if not messages:
928             AddMessage(template)
929
930     #################### PCUs
931     
932     ### Setup Initial PCU information
933     pcu_types = [{'model': 'AP79xx',
934           'name': 'APC AP79xx',
935           'pcu_protocol_types': [{ 'port': 80,
936                                   'protocol': 'APC79xxHttp',
937                                   'supported': False},
938                                  { 'port': 23,
939                                   'protocol': 'APC79xx',
940                                   'supported': True},
941                                  { 'port': 22,
942                                   'protocol': 'APC79xx',
943                                   'supported': True}],
944           },
945          {'model': 'Masterswitch',
946           'name': 'APC Masterswitch',
947           'pcu_protocol_types': [{ 'port': 80,
948                                   'protocol': 'APCMasterHttp',
949                                   'supported': False},
950                                  { 'port': 23,
951                                   'protocol': 'APCMaster',
952                                   'supported': True},
953                                  { 'port': 22,
954                                   'protocol': 'APCMaster',
955                                   'supported': True}],
956           },
957          {'model': 'DS4-RPC',
958           'name': 'BayTech DS4-RPC',
959           'pcu_protocol_types': [{ 'port': 80,
960                                   'protocol': 'BayTechHttp',
961                                   'supported': False},
962                                  { 'port': 23,
963                                   'protocol': 'BayTech',
964                                   'supported': True},
965                                  { 'port': 22,
966                                   'protocol': 'BayTech',
967                                   'supported': True}],
968           },
969          {'model': 'IP-41x_IP-81x',
970           'name': 'Dataprobe IP-41x & IP-81x',
971           'pcu_protocol_types': [ { 'port': 23,
972                                   'protocol': 'IPALTelnet',
973                                   'supported': True},
974                                   { 'port': 80,
975                                   'protocol': 'IPALHttp',
976                                   'supported': False}],
977           },
978          {'model': 'DRAC3',
979           'name': 'Dell RAC Version 3',
980           'pcu_protocol_types': [],
981           },
982          {'model': 'DRAC4',
983           'name': 'Dell RAC Version 4',
984           'pcu_protocol_types': [{ 'port': 443,
985                                   'protocol': 'DRACRacAdm',
986                                   'supported': True},
987                                  { 'port': 80,
988                                   'protocol': 'DRACRacAdm',
989                                   'supported': False},
990                                  { 'port': 22,
991                                   'protocol': 'DRAC',
992                                   'supported': True}],
993           },
994          {'model': 'ePowerSwitch',
995           'name': 'ePowerSwitch 1/4/8x',
996           'pcu_protocol_types': [{ 'port': 80,
997                                   'protocol': 'ePowerSwitch',
998                                   'supported': True}],
999           },
1000          {'model': 'ilo2',
1001           'name': 'HP iLO2 (Integrated Lights-Out)',
1002           'pcu_protocol_types': [{ 'port': 443,
1003                                   'protocol': 'HPiLOHttps',
1004                                   'supported': True},
1005                                  { 'port': 22,
1006                                   'protocol': 'HPiLO',
1007                                   'supported': True}],
1008           },
1009          {'model': 'ilo1',
1010           'name': 'HP iLO version 1',
1011           'pcu_protocol_types': [],
1012           },
1013          {'model': 'PM211-MIP',
1014           'name': 'Infratec PM221-MIP',
1015           'pcu_protocol_types': [],
1016           },
1017          {'model': 'AMT2.5',
1018           'name': 'Intel AMT v2.5 (Active Management Technology)',
1019           'pcu_protocol_types': [],
1020           },
1021          {'model': 'AMT3.0',
1022           'name': 'Intel AMT v3.0 (Active Management Technology)',
1023           'pcu_protocol_types': [],
1024           },
1025          {'model': 'WTI_IPS-4',
1026           'name': 'Western Telematic (WTI IPS-4)',
1027           'pcu_protocol_types': [],
1028           },
1029          {'model': 'unknown',
1030           'name': 'Unknown Vendor or Model',
1031           'pcu_protocol_types': [{ 'port': 443,
1032                                   'protocol': 'UnknownPCU',
1033                                   'supported': False},
1034                                  { 'port': 80,
1035                                   'protocol': 'UnknownPCU',
1036                                   'supported': False},
1037                                  { 'port': 23,
1038                                   'protocol': 'UnknownPCU',
1039                                   'supported': False},
1040                                  { 'port': 22,
1041                                   'protocol': 'UnknownPCU',
1042                                   'supported': False}],
1043           }]
1044
1045     # Get all model names
1046     pcu_models = [type['model'] for type in GetPCUTypes()]
1047     for type in pcu_types:
1048         protocol_types = type['pcu_protocol_types']
1049         # Take this value out of the struct.
1050         del type['pcu_protocol_types']
1051         if type['model'] not in pcu_models:
1052             # Add the name/model info into DB
1053             id = AddPCUType(type)
1054             # for each protocol, also add this.
1055             for ptype in protocol_types:
1056                 AddPCUProtocolType(id, ptype)
1057
1058         default_boot_states = [
1059                 'boot',
1060                 'failboot',
1061                 'safeboot',
1062                 'install',
1063                 'reinstall',
1064                 'disabled',
1065         ]
1066
1067         current_boot_states = GetBootStates()
1068         for state in default_boot_states:
1069                 if state not in current_boot_states:
1070                         AddBootState(state)
1071
1072         # TODO: Delete old boot states. 
1073         # NOTE: Only do this if all federating peers have the new default boot states above.
1074         #for state in current_boot_states:
1075         #       if state not in default_boot_states:
1076         #               DeleteBootState(state)
1077
1078
1079 if __name__ == '__main__':
1080     main()
1081
1082 # Local variables:
1083 # tab-width: 4
1084 # mode: python
1085 # End: