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