3 # Bootstraps the PLC database with a default administrator account and
6 # Mark Huang <mlhuang@cs.princeton.edu>
7 # Copyright (C) 2006 The Trustees of Princeton University
9 # $Id: api-config,v 1.7 2006/05/09 19:52:01 mlhuang Exp $
13 (plcapi, moreopts, argv) = plcapilib.plcapi(globals())
14 from plc_config import PLCConfiguration
19 cfg = PLCConfiguration()
21 variables = cfg.variables()
23 # Load variables into dictionaries
24 (category, variablelist) = variables['plc']
25 plc = dict(zip(variablelist.keys(),
26 [variable['value'] for variable in variablelist.values()]))
28 (category, variablelist) = variables['plc_www']
29 plc_www = dict(zip(variablelist.keys(),
30 [variable['value'] for variable in variablelist.values()]))
32 (category, variablelist) = variables['plc_api']
33 plc_api = dict(zip(variablelist.keys(),
34 [variable['value'] for variable in variablelist.values()]))
36 # Create/update the default administrator account (should be
38 admin = { 'person_id': 2,
39 'first_name': "Default",
40 'last_name': "Administrator",
41 'email': plc['root_user'],
42 'password': plc['root_password'] }
43 persons = AdmGetPersons([admin['person_id']])
45 person_id = AdmAddPerson(admin['first_name'], admin['last_name'], admin)
46 if person_id != admin['person_id']:
47 # Huh? Someone deleted the account manually from the database.
48 AdmDeletePerson(person_id)
49 raise Exception, "Someone deleted the \"%s %s\" account from the database!" % \
50 (admin['first_name'], admin['last_name'])
51 AdmSetPersonEnabled(person_id, True)
53 person_id = persons[0]['person_id']
54 AdmUpdatePerson(person_id, admin)
56 # Create/update the default site (should be site_id 1)
57 if plc_www['port'] == '80':
58 url = "http://" + plc_www['host'] + "/"
59 elif plc_www['port'] == '443':
60 url = "https://" + plc_www['host'] + "/"
62 url = "http://" + plc_www['host'] + ":" + plc_www['port'] + "/"
63 site = { 'site_id': 1,
64 'name': plc['name'] + " Central",
65 'abbreviated_name': plc['name'],
66 # XXX Default site slice_prefix/login_base must be "pl_"
67 # 'login_base': plc['slice_prefix'],
73 sites = AdmGetSites([site['site_id']])
75 site_id = AdmAddSite(site['name'], site['abbreviated_name'], site['login_base'], site)
76 if site_id != site['site_id']:
77 AdmDeleteSite(site_id)
78 raise Exception, "Someone deleted the \"%s\" site from the database!" % \
82 # Must call AdmUpdateSite() even after AdmAddSite() to update max_slices
83 site_id = sites[0]['site_id']
84 # XXX login_base cannot be updated
85 del site['login_base']
86 AdmUpdateSite(site_id, site)
88 # The default administrator account must be associated with a site
90 AdmAddPersonToSite(admin['person_id'], site['site_id'])
91 AdmSetPersonPrimarySite(admin['person_id'], site['site_id'])
93 # Grant admin and PI roles to the default administrator account
94 AdmGrantRoleToPerson(admin['person_id'], 10)
95 AdmGrantRoleToPerson(admin['person_id'], 20)
97 # Read and parse /etc/hosts
99 for line in file("/etc/hosts"):
102 if len(words) > 1 and words[0] != "#":
103 hosts[words[0]] = words[1:]
105 nodes = AdmGetNodes([], ['node_id', 'hostname'])
107 # Get the primary IP address for each node
110 AdmGetAllNodeNetworks(node['node_id'])
111 nodenetworks_list = plcapi.commit()
112 for i, nodenetworks in enumerate(nodenetworks_list):
113 for nodenetwork in nodenetworks:
114 if nodenetwork['hostname']:
115 hostname = nodenetwork['hostname']
117 hostname = nodes[i]['hostname']
119 if hosts.has_key(nodenetwork['ip']):
120 if hostname not in hosts[nodenetwork['ip']]:
121 hosts[nodenetwork['ip']].append(hostname)
123 hosts[nodenetwork['ip']] = [hostname]
126 etc_hosts = open("/etc/hosts", "w")
127 for ip, hostnames in hosts.iteritems():
128 etc_hosts.write(ip + "\t" + " ".join(hostnames) + "\n")
131 # Setup default PlanetLabConf entries
132 default_conf_files = [
135 'source': 'PlanetLabConf/ntpconf.php',
136 'dest': '/etc/ntp.conf',
137 'file_permissions': '644',
138 'file_owner': 'root',
139 'file_group': 'root',
140 'preinstall_cmd': '',
141 'postinstall_cmd': '/etc/rc.d/init.d/ntpd restart',
143 'ignore_cmd_errors': 0,
146 'source': 'PlanetLabConf/ntptickers.php',
147 'dest': '/etc/ntp/step-tickers',
148 'file_permissions': '644',
149 'file_owner': 'root',
150 'file_group': 'root',
151 'preinstall_cmd': '',
152 'postinstall_cmd': '/etc/rc.d/init.d/ntpd restart',
154 'ignore_cmd_errors': 0,
157 # SSH server configuration
159 'source': 'PlanetLabConf/sshd_config',
160 'dest': '/etc/ssh/sshd_config',
161 'file_permissions': '600',
162 'file_owner': 'root',
163 'file_group': 'root',
164 'preinstall_cmd': '',
165 'postinstall_cmd': '/etc/init.d/sshd restart',
167 'ignore_cmd_errors': 0,
170 # Administrative SSH keys
172 'source': 'PlanetLabConf/keys.php?root',
173 'dest': '/root/.ssh/authorized_keys',
174 'file_permissions': '644',
175 'file_owner': 'root',
176 'file_group': 'root',
177 'preinstall_cmd': '',
178 'postinstall_cmd': '',
180 'ignore_cmd_errors': 0,
183 'source': 'PlanetLabConf/keys.php?site_admin',
184 'dest': '/home/site_admin/.ssh/authorized_keys',
185 'file_permissions': '644',
186 'file_owner': 'site_admin',
187 'file_group': 'site_admin',
188 'preinstall_cmd': 'grep -q site_admin /etc/passwd',
189 'postinstall_cmd': '',
191 'ignore_cmd_errors': 0,
194 'source': 'PlanetLabConf/keys.php?role=admin',
195 'dest': '/home/pl_admin/.ssh/authorized_keys',
196 'file_permissions': '644',
197 'file_owner': 'pl_admin',
198 'file_group': 'pl_admin',
199 'preinstall_cmd': 'grep -q pl_admin /etc/passwd',
200 'postinstall_cmd': '',
202 'ignore_cmd_errors': 0,
205 # Log rotation configuration
207 'source': 'PlanetLabConf/logrotate.conf',
208 'dest': '/etc/logrotate.conf',
209 'file_permissions': '644',
210 'file_owner': 'root',
211 'file_group': 'root',
212 'preinstall_cmd': '',
213 'postinstall_cmd': '',
215 'ignore_cmd_errors': 0,
218 # updatedb/locate nightly cron job
220 'source': 'PlanetLabConf/slocate.cron',
221 'dest': '/etc/cron.daily/slocate.cron',
222 'file_permissions': '755',
223 'file_owner': 'root',
224 'file_group': 'root',
225 'preinstall_cmd': '',
226 'postinstall_cmd': '',
228 'ignore_cmd_errors': 0,
233 'source': 'PlanetLabConf/yum.conf.php?gpgcheck=1',
234 'dest': '/etc/yum.conf',
235 'file_permissions': '644',
236 'file_owner': 'root',
237 'file_group': 'root',
238 'preinstall_cmd': '',
239 'postinstall_cmd': '',
241 'ignore_cmd_errors': 0,
244 'source': 'PlanetLabConf/delete-rpm-list-production',
245 'dest': '/etc/planetlab/delete-rpm-list',
246 'file_permissions': '644',
247 'file_owner': 'root',
248 'file_group': 'root',
249 'preinstall_cmd': '',
250 'postinstall_cmd': '',
252 'ignore_cmd_errors': 0,
257 'source': 'PlanetLabConf/get_plc_config.php',
258 'dest': '/etc/planetlab/plc_config',
259 'file_permissions': '644',
260 'file_owner': 'root',
261 'file_group': 'root',
262 'preinstall_cmd': '',
263 'postinstall_cmd': '',
265 'ignore_cmd_errors': 0,
268 'source': 'PlanetLabConf/get_plc_config.php?python',
269 'dest': '/etc/planetlab/plc_config.py',
270 'file_permissions': '644',
271 'file_owner': 'root',
272 'file_group': 'root',
273 'preinstall_cmd': '',
274 'postinstall_cmd': '',
276 'ignore_cmd_errors': 0,
279 'source': 'PlanetLabConf/get_plc_config.php?perl',
280 'dest': '/etc/planetlab/plc_config.pl',
281 'file_permissions': '644',
282 'file_owner': 'root',
283 'file_group': 'root',
284 'preinstall_cmd': '',
285 'postinstall_cmd': '',
287 'ignore_cmd_errors': 0,
290 'source': 'PlanetLabConf/get_plc_config.php?php',
291 'dest': '/etc/planetlab/php/plc_config.php',
292 'file_permissions': '644',
293 'file_owner': 'root',
294 'file_group': 'root',
295 'preinstall_cmd': '',
296 'postinstall_cmd': '',
298 'ignore_cmd_errors': 0,
301 # Node Manager configuration
303 'source': 'PlanetLabConf/pl_nm-v3.conf',
304 'dest': '/etc/planetlab/pl_nm.conf',
305 'file_permissions': '644',
306 'file_owner': 'root',
307 'file_group': 'root',
308 'preinstall_cmd': '',
309 'postinstall_cmd': '/etc/init.d/pl_nm restart',
311 'ignore_cmd_errors': 0,
314 'source': 'PlanetLabConf/RootResources/plc_slice_pool.php',
315 'dest': '/home/pl_nm/RootResources/plc_slice_pool',
316 'file_permissions': '644',
317 'file_owner': 'pl_nm',
318 'file_group': 'pl_nm',
319 'preinstall_cmd': '',
320 'postinstall_cmd': '',
322 'ignore_cmd_errors': 0,
325 'source': 'PlanetLabConf/RootResources/pl_conf.py',
326 'dest': '/home/pl_nm/RootResources/pl_conf',
327 'file_permissions': '644',
328 'file_owner': 'pl_nm',
329 'file_group': 'pl_nm',
330 'preinstall_cmd': '',
331 'postinstall_cmd': '/etc/init.d/pl_nm restart',
333 'ignore_cmd_errors': 0,
336 'source': 'PlanetLabConf/RootResources/pl_netflow.py',
337 'dest': '/home/pl_nm/RootResources/pl_netflow',
338 'file_permissions': '644',
339 'file_owner': 'pl_nm',
340 'file_group': 'pl_nm',
341 'preinstall_cmd': '',
342 'postinstall_cmd': '',
344 'ignore_cmd_errors': 0,
347 # Proper configuration
349 'source': 'PlanetLabConf/propd-NM-1.0.conf',
350 'dest': '/etc/proper/propd.conf',
351 'file_permissions': '644',
352 'file_owner': 'root',
353 'file_group': 'root',
354 'preinstall_cmd': '',
355 'postinstall_cmd': '/etc/init.d/proper restart',
357 'ignore_cmd_errors': 1,
362 'source': 'PlanetLabConf/bwlimit.php',
363 'dest': '/etc/planetlab/bwcap',
364 'file_permissions': '644',
365 'file_owner': 'root',
366 'file_group': 'root',
367 'preinstall_cmd': '',
368 'postinstall_cmd': '/etc/init.d/pl_nm restart',
370 'ignore_cmd_errors': 1,
375 'source': 'PlanetLabConf/proxies.php',
376 'dest': '/etc/planetlab/proxies',
377 'file_permissions': '644',
378 'file_owner': 'root',
379 'file_group': 'root',
380 'preinstall_cmd': '',
381 'postinstall_cmd': '',
383 'ignore_cmd_errors': 0,
386 # Firewall configuration
388 'source': 'PlanetLabConf/iptables',
389 'dest': '/etc/sysconfig/iptables',
390 'file_permissions': '600',
391 'file_owner': 'root',
392 'file_group': 'root',
393 'preinstall_cmd': '',
394 'postinstall_cmd': '',
396 'ignore_cmd_errors': 0,
399 'source': 'PlanetLabConf/blacklist.php',
400 'dest': '/etc/planetlab/blacklist',
401 'file_permissions': '600',
402 'file_owner': 'root',
403 'file_group': 'root',
404 'preinstall_cmd': '',
405 'postinstall_cmd': '/sbin/iptables-restore --noflush < /etc/planetlab/blacklist',
407 'ignore_cmd_errors': 1,
412 'source': 'PlanetLabConf/issue.php',
413 'dest': '/etc/issue',
414 'file_permissions': '644',
415 'file_owner': 'root',
416 'file_group': 'root',
417 'preinstall_cmd': '',
418 'postinstall_cmd': '',
420 'ignore_cmd_errors': 0,
425 'source': 'PlanetLabConf/sysctl.php',
426 'dest': '/etc/sysctl.conf',
427 'file_permissions': '644',
428 'file_owner': 'root',
429 'file_group': 'root',
430 'preinstall_cmd': '',
431 'postinstall_cmd': '/sbin/sysctl -e -p /etc/sysctl.conf',
433 'ignore_cmd_errors': 0,
436 # Sendmail configuration
438 'source': 'PlanetLabConf/alpha-sendmail.mc',
439 'dest': '/etc/mail/sendmail.mc',
440 'file_permissions': '644',
441 'file_owner': 'root',
442 'file_group': 'root',
443 'preinstall_cmd': '',
444 'postinstall_cmd': '',
446 'ignore_cmd_errors': 0,
449 'source': 'PlanetLabConf/alpha-sendmail.cf',
450 'dest': '/etc/mail/sendmail.cf',
451 'file_permissions': '644',
452 'file_owner': 'root',
453 'file_group': 'root',
454 'preinstall_cmd': '',
455 'postinstall_cmd': 'service sendmail restart',
457 'ignore_cmd_errors': 0,
462 'source': 'PlanetLabConf/RPM-GPG-KEY-fedora',
463 'dest': '/etc/pki/rpm-gpg/RPM-GPG-KEY-fedora',
464 'file_permissions': '644',
465 'file_owner': 'root',
466 'file_group': 'root',
467 'preinstall_cmd': '',
468 'postinstall_cmd': 'rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-fedora',
470 'ignore_cmd_errors': 0,
473 'source': 'PlanetLabConf/get_gpg_key.php',
474 'dest': '/etc/pki/rpm-gpg/RPM-GPG-KEY-planetlab',
475 'file_permissions': '644',
476 'file_owner': 'root',
477 'file_group': 'root',
478 'preinstall_cmd': '',
479 'postinstall_cmd': 'rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-planetlab',
481 'ignore_cmd_errors': 0,
484 # Ping of death configuration
486 'source': 'PlanetLabConf/ipod.conf.php',
487 'dest': '/etc/ipod.conf',
488 'file_permissions': '644',
489 'file_owner': 'root',
490 'file_group': 'root',
491 'preinstall_cmd': '',
492 'postinstall_cmd': '',
494 'ignore_cmd_errors': 0,
499 'source': 'PlanetLabConf/v3-sudoers.php',
500 'dest': '/etc/sudoers',
501 'file_permissions': '440',
502 'file_owner': 'root',
503 'file_group': 'root',
504 'preinstall_cmd': '',
505 'postinstall_cmd': '/usr/sbin/visudo -c',
507 'ignore_cmd_errors': 0,
510 # Get list of existing (enabled, global) files
511 conf_files = AdmGetConfFile()
512 conf_files = filter(lambda conf_file: conf_file['enabled'] and \
513 not conf_file['node_id'] and \
514 not conf_file['nodegroup_id'],
516 dests = [conf_file['dest'] for conf_file in conf_files]
517 conf_files = dict(zip(dests, conf_files))
519 # Create/update default PlanetLabConf entries
520 for default_conf_file in default_conf_files:
521 if default_conf_file['dest'] not in dests:
522 AdmCreateConfFile(default_conf_file['enabled'],
523 default_conf_file['source'],
524 default_conf_file['dest'],
525 default_conf_file['file_permissions'],
526 default_conf_file['file_owner'],
527 default_conf_file['file_group'],
528 default_conf_file['preinstall_cmd'],
529 default_conf_file['postinstall_cmd'],
530 default_conf_file['error_cmd'],
531 default_conf_file['ignore_cmd_errors'],
532 default_conf_file['always_update'])
534 conf_file = conf_files[default_conf_file['dest']]
535 AdmUpdateConfFile(conf_file['conf_file_id'], default_conf_file)
537 # Setup default slice attribute types
538 default_attribute_types = [
539 # Slice type (only vserver is supported)
540 {'name': "plc_slice_type",
541 'description': "Type of slice rspec to be created",
542 'is_exclusive': True, 'min_role_id': 20, 'max_per_slice': 1,
543 'value_fields': [{'description': "rspec class",
547 # Slice initialization script
548 {'name': "initscript",
549 'description': "slice initialization script",
550 'is_exclusive': False, 'min_role_id': 10, 'max_per_slice': 1,
551 'value_fields': [{'description': "",
552 'name': "initscript_id",
553 'type': "integer"}]},
555 # CPU share (general_prop_share is deprecated)
556 {'name': "general_prop_share",
557 'description': "general share",
558 'is_exclusive': False, 'min_role_id': 10, 'max_per_slice': 1,
559 'value_fields': [{'description': "",
560 'name': "general_prop_share",
561 'type': "integer"}]},
562 {'name': "nm_cpu_share",
563 'description': "Number of CPU shares to be allocated to slice",
564 'is_exclusive': True, 'min_role_id': 10, 'max_per_slice': 1,
565 'value_fields': [{'description': "number of shares",
567 'type': "integer"}]},
570 {'name': "nm_net_min_rate",
571 'description': "Minimum network Tx bandwidth",
572 'is_exclusive': True, 'min_role_id': 10, 'max_per_slice': 1,
573 'value_fields': [{'description': "rate (kbps)",
575 'type': "integer"}]},
576 {'name': "nm_net_max_rate",
577 'description': "Maximum network Tx bandwidth",
578 'is_exclusive': True, 'min_role_id': 10, 'max_per_slice': 1,
579 'value_fields': [{'description': "rate (kbps)",
581 'type': "integer"}]},
582 {'name': "nm_net_avg_rate",
583 'description': "Average daily network Tx bandwidth",
584 'is_exclusive': True, 'min_role_id': 10, 'max_per_slice': 1,
585 'value_fields': [{'description': "rate (kbps)",
587 'type': "integer"}]},
588 {'name': "nm_net_exempt_min_rate",
589 'description': "Minimum network Tx bandwidth to Internet2 destinations",
590 'is_exclusive': True, 'min_role_id': 10, 'max_per_slice': 1,
591 'value_fields': [{'description': "rate (kbps)",
593 'type': "integer"}]},
594 {'name': "nm_net_exempt_max_rate",
595 'description': "Maximum network Tx bandwidth to Internet2 destinations",
596 'is_exclusive': True, 'min_role_id': 10, 'max_per_slice': 1,
597 'value_fields': [{'description': "rate (kbps)",
599 'type': "integer"}]},
600 {'name': "nm_net_exempt avg_rate",
601 'description': "Average daily network Tx bandwidth to Internet2 destinations",
602 'is_exclusive': True, 'min_role_id': 10, 'max_per_slice': 1,
603 'value_fields': [{'description': "rate (kbps)",
605 'type': "integer"}]},
608 {'name': "nm_disk_quota",
609 'description': "Disk quota",
610 'is_exclusive': True, 'min_role_id': 10, 'max_per_slice': 1,
611 'value_fields': [{'description': "Number of 1k disk blocks",
613 'type': "integer"}]},
615 # Special attributes applicable to Slice Creation Service (pl_conf) slice
616 {'name': "plc_agent_version",
617 'description': "Version of PLC agent (slice creation service) software to be deployed",
618 'is_exclusive': True, 'min_role_id': 10, 'max_per_slice': 1,
619 'value_fields': [{'description': "current version of PLC agent (SCS)",
622 {'name': "plc_ticket_pubkey",
623 'description': "Public key used to verify PLC-signed tickets",
624 'is_exclusive': True, 'min_role_id': 10, 'max_per_slice': 1,
625 'value_fields': [{'description': "PEM-encoded public key",
629 # Get list of existing attribute types
630 attribute_types = SliceAttributeTypeList()
632 # Create/update default slice attribute types
633 for default_attribute_type in default_attribute_types:
634 if default_attribute_type['name'] not in attribute_types:
635 SliceAttributeTypeCreate(default_attribute_type['name'],
636 default_attribute_type['description'],
637 default_attribute_type['min_role_id'],
638 default_attribute_type['max_per_slice'],
639 default_attribute_type['is_exclusive'],
640 default_attribute_type['value_fields'])
642 # XXX No way to update slice attribute types
645 # Get contents of SSL public certificate used for signing tickets
647 plc_ticket_pubkey = ""
648 for line in file(plc_api['ssl_key_pub']):
650 if line[0:5] != "-----":
651 # XXX The embedded newlines matter, do not strip()!
652 plc_ticket_pubkey += line
654 plc_ticket_pubkey = '%KEY%'
656 # Create/update system slices
657 slices = [{'name': "pl_conf",
658 'description': "PlanetLab Slice Creation Service (SCS)",
660 'attributes': {'plc_slice_type': {'type': "VServerSlice"},
661 'plc_agent_version': {'version': "1.0"},
662 'plc_ticket_pubkey': {'key': plc_ticket_pubkey}}},
663 {'name': "pl_conf_vserverslice",
664 'description': "Default attributes for vserver slices",
666 'attributes': {'nm_cpu_share': {'cpu_share': 32},
667 'plc_slice_type': {'type': "VServerSlice"},
668 'nm_disk_quota': {'quota': 5000000}}}]
671 SliceInfo([slice['name']])
673 SliceCreate(slice['name'])
674 SliceSetInstantiationMethod(slice['name'], 'plc-instantiated')
675 SliceUpdate(slice['name'], slice['url'], slice['description'])
677 SliceRenew(slice['name'], sys.maxint)
678 # Create/update all attributes
679 for attribute, values in slice['attributes'].iteritems():
680 SliceAttributeSet(slice['name'], attribute, values)
683 if __name__ == '__main__':