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.1.1.1 2006/03/27 17:36:46 mlhuang Exp $
13 (plcapi, moreopts, argv) = plcapilib.plcapi(globals())
14 from plc_config import PLCConfiguration
20 cfg = PLCConfiguration()
22 variables = cfg.variables()
24 # Load variables into dictionaries
25 (category, variablelist) = variables['plc']
26 plc = dict(zip(variablelist.keys(),
27 [variable['value'] for variable in variablelist.values()]))
29 (category, variablelist) = variables['plc_www']
30 plc_www = dict(zip(variablelist.keys(),
31 [variable['value'] for variable in variablelist.values()]))
33 (category, variablelist) = variables['plc_api']
34 plc_api = dict(zip(variablelist.keys(),
35 [variable['value'] for variable in variablelist.values()]))
37 # Create/update the default administrator account (should be
39 admin = { 'person_id': 2,
40 'first_name': "Default",
41 'last_name': "Administrator",
42 'email': plc['root_user'],
43 'password': plc['root_password'] }
44 persons = AdmGetPersons([admin['person_id']])
46 person_id = AdmAddPerson(admin['first_name'], admin['last_name'], admin)
47 if person_id != admin['person_id']:
48 # Huh? Someone deleted the account manually from the database.
49 AdmDeletePerson(person_id)
50 raise Exception, "Someone deleted the \"%s %s\" account from the database!" % \
51 (admin['first_name'], admin['last_name'])
52 AdmSetPersonEnabled(person_id, True)
54 person_id = persons[0]['person_id']
55 AdmUpdatePerson(person_id, admin)
57 # Create/update the default site (should be site_id 0)
58 if plc_www['port'] == '80':
59 url = "http://" + plc_www['host'] + "/"
60 elif plc_www['port'] == '443':
61 url = "https://" + plc_www['host'] + "/"
63 url = "http://" + plc_www['host'] + ":" + plc_www['port'] + "/"
64 site = { 'site_id': 1,
65 'name': plc['name'] + " Central",
66 'abbreviated_name': plc['name'],
67 # XXX Default site slice_prefix/login_base must be "pl_"
68 # 'login_base': plc['slice_prefix'],
74 sites = AdmGetSites([site['site_id']])
76 site_id = AdmAddSite(site['name'], site['abbreviated_name'], site['login_base'], site)
77 if site_id != site['site_id']:
78 AdmDeleteSite(site_id)
79 raise Exception, "Someone deleted the \"%s\" site from the database!" % \
82 site_id = sites[0]['site_id']
83 # XXX login_base cannot be updated
84 del site['login_base']
85 AdmUpdateSite(site_id, site)
87 # The default administrator account must be associated with a site
89 AdmAddPersonToSite(admin['person_id'], site['site_id'])
90 AdmSetPersonPrimarySite(admin['person_id'], site['site_id'])
92 # Grant admin and PI roles to the default administrator account
93 AdmGrantRoleToPerson(admin['person_id'], 10)
94 AdmGrantRoleToPerson(admin['person_id'], 20)
96 # Further bootstrap the database. A few PlanetLabConf entries are
97 # absolutely required, and NM requires the slice tables to be
100 # XXX This data should really become part of the DB schema so that
101 # we don't have to copy it from PLC. For now, this code is only
102 # intended to be called at build time, when we know that we have
103 # access to PLC. Once the tables have been populated, this code
104 # should never be called again and PLC access is not required,
105 # i.e., end users of MyPLC should never see this code be executed.
107 # Use xmlrpclib to connect to PLC temporarily. plcapilib cannot
108 # connect to multiple servers at once.
109 auth = {'AuthMethod': 'anonymous'}
112 conf_files = AdmGetConfFile()
115 PLC = xmlrpclib.Server("https://www.planet-lab.org/PLCAPI/")
116 for conf_file in PLC.AnonAdmGetConfFile(auth):
117 if conf_file['enabled'] and \
118 not conf_file['node_id'] and \
119 not conf_file['nodegroup_id']:
120 AdmCreateConfFile(conf_file['enabled'],
123 conf_file['file_permissions'],
124 conf_file['file_owner'],
125 conf_file['file_group'],
126 conf_file['preinstall_cmd'],
127 conf_file['postinstall_cmd'],
128 conf_file['error_cmd'],
129 conf_file['ignore_cmd_errors'],
130 conf_file['always_update'])
132 # Setup default slice attribute types, slices, and
133 # attributes. These are hard-coded here because we cannot safely
134 # support an anonymous interface to the SliceAttribute functions,
135 # yet we also do not want to require API authentication for
138 if not SliceAttributeTypeList():
139 # Create system attribute types
140 attribute_types = [{'name': "general_prop_share",
141 'description': "general share",
142 'is_exclusive': False, 'min_role_id': 10, 'max_per_slice': 1,
143 'value_fields': [{'description': "",
144 'name': "general_prop_share",
145 'type': "integer"}]},
146 {'name': "initscript",
147 'description': "slice initialization script",
148 'is_exclusive': False, 'min_role_id': 10, 'max_per_slice': 1,
149 'value_fields': [{'description': "",
150 'name': "initscript_id",
151 'type': "integer"}]},
152 {'name': "plc_slice_type",
153 'description': "Type of slice rspec to be created",
154 'is_exclusive': True, 'min_role_id': 20, 'max_per_slice': 1,
155 'value_fields': [{'description': "rspec class",
158 {'name': "nm_cpu_share",
159 'description': "Number of CPU shares to be allocated to slice",
160 'is_exclusive': True, 'min_role_id': 10, 'max_per_slice': 1,
161 'value_fields': [{'description': "number of shares",
163 'type': "integer"}]},
164 {'name': "plc_agent_version",
165 'description': "Version of PLC agent (slice creation service) software to be deployed",
166 'is_exclusive': True, 'min_role_id': 10, 'max_per_slice': 1,
167 'value_fields': [{'description': "current version of PLC agent (SCS)",
170 {'name': "plc_ticket_pubkey",
171 'description': "Public key used to verify PLC-signed tickets",
172 'is_exclusive': True, 'min_role_id': 10, 'max_per_slice': 1,
173 'value_fields': [{'description': "PEM-encoded public key",
176 {'name': "nm_disk_quota",
177 'description': "Disk quota",
178 'is_exclusive': True, 'min_role_id': 10, 'max_per_slice': 1,
179 'value_fields': [{'description': "Number of 1k disk blocks",
181 'type': "integer"}]}]
182 for attribute_type in attribute_types:
183 SliceAttributeTypeCreate(attribute_type['name'], attribute_type['description'],
184 attribute_type['min_role_id'], attribute_type['max_per_slice'],
185 attribute_type['is_exclusive'], attribute_type['value_fields'])
187 if not SliceListNames():
188 # Get contents of SSL public certificate used for signing tickets
190 plc_ticket_pubkey = ""
191 for line in file(plc_api['ssl_key_pub']):
193 if line[0:5] != "-----":
194 # XXX The embedded newlines matter, do not strip()!
195 plc_ticket_pubkey += line
197 plc_ticket_pubkey = '%KEY%'
199 # Create system slices
200 slices = [{'name': "pl_conf",
201 'description': "PlanetLab Slice Creation Service (SCS)",
203 'attributes': {'plc_slice_type': {'type': "VServerSlice"},
204 'plc_agent_version': {'version': "1.0"},
205 'plc_ticket_pubkey': {'key': plc_ticket_pubkey}}},
206 {'name': "pl_conf_vserverslice",
207 'description': "Default attributes for vserver slices",
209 'attributes': {'nm_cpu_share': {'cpu_share': 32},
210 'plc_slice_type': {'type': "VServerSlice"},
211 'nm_disk_quota': {'quota': 5000000}}}]
213 SliceCreate(slice['name'])
214 SliceUpdate(slice['name'], slice['url'], slice['description'])
215 SliceSetInstantiationMethod(slice['name'], 'plc-instantiated')
217 SliceRenew(slice['name'], sys.maxint)
218 for attribute, values in slice['attributes'].iteritems():
219 SliceAttributeAdd(slice['name'], attribute, values)
222 if __name__ == '__main__':