#!/usr/bin/env /usr/bin/plcsh # # Bootstraps the PLC database with a default administrator account and # a default site, defines default slice attribute types, and # creates/updates default system slices. # # Mark Huang # Copyright (C) 2006 The Trustees of Princeton University # # $Id$ # from plc_config import PLCConfiguration import sys def main(): cfg = PLCConfiguration() cfg.load() variables = cfg.variables() # Load variables into dictionaries for category_id, (category, variablelist) in variables.iteritems(): globals()[category_id] = dict(zip(variablelist.keys(), [variable['value'] for variable in variablelist.values()])) # Create/update the default administrator account (should be # person_id 2). admin = { 'person_id': 2, 'first_name': "Default", 'last_name': "Administrator", 'email': plc['root_user'], 'password': plc['root_password'] } persons = GetPersons([admin['person_id']]) if not persons: person_id = AddPerson(admin) if person_id != admin['person_id']: # Huh? Someone deleted the account manually from the database. DeletePerson(person_id) raise Exception, "Someone deleted the \"%s %s\" account from the database!" % \ (admin['first_name'], admin['last_name']) UpdatePerson(person_id, { 'enabled': True }) else: person_id = persons[0]['person_id'] UpdatePerson(person_id, admin) # Create/update the default site (should be site_id 1) if plc_www['port'] == '80': url = "http://" + plc_www['host'] + "/" elif plc_www['port'] == '443': url = "https://" + plc_www['host'] + "/" else: url = "http://" + plc_www['host'] + ":" + plc_www['port'] + "/" site = { 'site_id': 1, 'name': plc['name'] + " Central", 'abbreviated_name': plc['name'], 'login_base': plc['slice_prefix'], 'is_public': False, 'url': url, 'max_slices': 100 } sites = GetSites([site['site_id']]) if not sites: site_id = AddSite(site['name'], site['abbreviated_name'], site['login_base'], site) if site_id != site['site_id']: DeleteSite(site_id) raise Exception, "Someone deleted the \"%s\" site from the database!" % \ site['name'] sites = [site] # Must call UpdateSite() even after AddSite() to update max_slices site_id = sites[0]['site_id'] UpdateSite(site_id, site) # The default administrator account must be associated with a site # in order to login. AddPersonToSite(admin['person_id'], site['site_id']) SetPersonPrimarySite(admin['person_id'], site['site_id']) # Grant admin and PI roles to the default administrator account AddRoleToPerson(10, admin['person_id']) AddRoleToPerson(20, admin['person_id']) # Setup default PlanetLabConf entries default_conf_files = [ # NTP configuration {'enabled': True, 'source': 'PlanetLabConf/ntp.conf.php', 'dest': '/etc/ntp.conf', 'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '/etc/rc.d/init.d/ntpd restart', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, {'enabled': True, 'source': 'PlanetLabConf/ntp/step-tickers.php', 'dest': '/etc/ntp/step-tickers', 'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '/etc/rc.d/init.d/ntpd restart', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, # SSH server configuration {'enabled': True, 'source': 'PlanetLabConf/sshd_config', 'dest': '/etc/ssh/sshd_config', 'file_permissions': '600', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '/etc/init.d/sshd restart', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, # Administrative SSH keys {'enabled': True, 'source': 'PlanetLabConf/keys.php?root', 'dest': '/root/.ssh/authorized_keys', 'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '/bin/chmod 700 /root/.ssh', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, {'enabled': True, 'source': 'PlanetLabConf/keys.php?site_admin', 'dest': '/home/site_admin/.ssh/authorized_keys', 'file_permissions': '644', 'file_owner': 'site_admin', 'file_group': 'site_admin', 'preinstall_cmd': 'grep -q site_admin /etc/passwd', 'postinstall_cmd': '/bin/chmod 700 /home/site_admin/.ssh', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, {'enabled': True, 'source': 'PlanetLabConf/keys.php?role=admin', 'dest': '/home/pl_admin/.ssh/authorized_keys', 'file_permissions': '644', 'file_owner': 'pl_admin', 'file_group': 'pl_admin', 'preinstall_cmd': 'grep -q pl_admin /etc/passwd', 'postinstall_cmd': '/bin/chmod 700 /home/pl_admin/.ssh', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, # Log rotation configuration {'enabled': True, 'source': 'PlanetLabConf/logrotate.conf', 'dest': '/etc/logrotate.conf', 'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, # updatedb/locate nightly cron job {'enabled': True, 'source': 'PlanetLabConf/slocate.cron', 'dest': '/etc/cron.daily/slocate.cron', 'file_permissions': '755', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, # YUM configuration {'enabled': True, 'source': 'PlanetLabConf/yum.conf.php?gpgcheck=1', 'dest': '/etc/yum.conf', 'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, {'enabled': True, 'source': 'PlanetLabConf/delete-rpm-list-production', 'dest': '/etc/planetlab/delete-rpm-list', 'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, # PLC configuration {'enabled': True, 'source': 'PlanetLabConf/get_plc_config.php', 'dest': '/etc/planetlab/plc_config', 'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, {'enabled': True, 'source': 'PlanetLabConf/get_plc_config.php?python', 'dest': '/etc/planetlab/plc_config.py', 'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, {'enabled': True, 'source': 'PlanetLabConf/get_plc_config.php?perl', 'dest': '/etc/planetlab/plc_config.pl', 'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, {'enabled': True, 'source': 'PlanetLabConf/get_plc_config.php?php', 'dest': '/etc/planetlab/php/plc_config.php', 'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, # XXX Required for old Node Manager # Node Manager configuration {'enabled': True, 'source': 'PlanetLabConf/pl_nm.conf', 'dest': '/etc/planetlab/pl_nm.conf', 'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '/etc/init.d/pl_nm restart', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, {'enabled': True, 'source': 'PlanetLabConf/RootResources/plc_slice_pool.php', 'dest': '/home/pl_nm/RootResources/plc_slice_pool', 'file_permissions': '644', 'file_owner': 'pl_nm', 'file_group': 'pl_nm', 'preinstall_cmd': '', 'postinstall_cmd': '', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, {'enabled': True, 'source': 'PlanetLabConf/RootResources/pl_conf.py', 'dest': '/home/pl_nm/RootResources/pl_conf', 'file_permissions': '644', 'file_owner': 'pl_nm', 'file_group': 'pl_nm', 'preinstall_cmd': '', 'postinstall_cmd': '/etc/init.d/pl_nm restart', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, {'enabled': True, 'source': 'PlanetLabConf/RootResources/pl_netflow.py', 'dest': '/home/pl_nm/RootResources/pl_netflow', 'file_permissions': '644', 'file_owner': 'pl_nm', 'file_group': 'pl_nm', 'preinstall_cmd': '', 'postinstall_cmd': '', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, # XXX Required for old Node Manager # Proper configuration {'enabled': True, 'source': 'PlanetLabConf/propd.conf', 'dest': '/etc/proper/propd.conf', 'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '/etc/init.d/proper restart', 'error_cmd': '', 'ignore_cmd_errors': True, 'always_update': False}, # XXX Required for old Node Manager # Bandwidth cap {'enabled': True, 'source': 'PlanetLabConf/bwlimit.php', 'dest': '/etc/planetlab/bwcap', 'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '/etc/init.d/pl_nm restart', 'error_cmd': '', 'ignore_cmd_errors': True, 'always_update': False}, # Proxy ARP setup {'enabled': True, 'source': 'PlanetLabConf/proxies.php', 'dest': '/etc/planetlab/proxies', 'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, # Firewall configuration {'enabled': True, 'source': 'PlanetLabConf/iptables', 'dest': '/etc/sysconfig/iptables', 'file_permissions': '600', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, {'enabled': True, 'source': 'PlanetLabConf/blacklist.php', 'dest': '/etc/planetlab/blacklist', 'file_permissions': '600', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '/sbin/iptables-restore --noflush < /etc/planetlab/blacklist', 'error_cmd': '', 'ignore_cmd_errors': True, 'always_update': False}, # /etc/issue {'enabled': True, 'source': 'PlanetLabConf/issue.php', 'dest': '/etc/issue', 'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, # Kernel parameters {'enabled': True, 'source': 'PlanetLabConf/sysctl.php', 'dest': '/etc/sysctl.conf', 'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '/sbin/sysctl -e -p /etc/sysctl.conf', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, # Sendmail configuration {'enabled': True, 'source': 'PlanetLabConf/sendmail.mc', 'dest': '/etc/mail/sendmail.mc', 'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, {'enabled': True, 'source': 'PlanetLabConf/sendmail.cf', 'dest': '/etc/mail/sendmail.cf', 'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': 'service sendmail restart', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, # GPG signing keys {'enabled': True, 'source': 'PlanetLabConf/RPM-GPG-KEY-fedora', 'dest': '/etc/pki/rpm-gpg/RPM-GPG-KEY-fedora', 'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': 'rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-fedora', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, {'enabled': True, 'source': 'PlanetLabConf/get_gpg_key.php', 'dest': '/etc/pki/rpm-gpg/RPM-GPG-KEY-planetlab', 'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': 'rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-planetlab', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, # Ping of death configuration {'enabled': True, 'source': 'PlanetLabConf/ipod.conf.php', 'dest': '/etc/ipod.conf', 'file_permissions': '644', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False}, # sudo configuration {'enabled': True, 'source': 'PlanetLabConf/sudoers', 'dest': '/etc/sudoers', 'file_permissions': '440', 'file_owner': 'root', 'file_group': 'root', 'preinstall_cmd': '', 'postinstall_cmd': '/usr/sbin/visudo -c', 'error_cmd': '', 'ignore_cmd_errors': False, 'always_update': False} ] # Get list of existing (enabled, global) files conf_files = GetConfFiles() conf_files = filter(lambda conf_file: conf_file['enabled'] and \ not conf_file['node_ids'] and \ not conf_file['nodegroup_ids'], conf_files) dests = [conf_file['dest'] for conf_file in conf_files] conf_files = dict(zip(dests, conf_files)) # Create/update default PlanetLabConf entries for default_conf_file in default_conf_files: if default_conf_file['dest'] not in dests: AddConfFile(default_conf_file) else: conf_file = conf_files[default_conf_file['dest']] UpdateConfFile(conf_file['conf_file_id'], default_conf_file) # Setup default slice attribute types default_attribute_types = [ # Slice type (only vserver is supported) {'name': "type", 'description': "Type of slice (e.g. vserver)", 'min_role_id': 20}, # System slice {'name': "system", 'description': "Is a default system slice (1) or not (0 or unset)", 'min_role_id': 10}, # Slice enabled (1) or suspended (0) {'name': "enabled", 'description': "Slice enabled (1 or unset) or suspended (0)", 'min_role_id': 10}, # Slice reference image {'name': "vref", 'description': "Reference image", 'min_role_id': 30}, # Slice initialization script {'name': "initscript", 'description': "Slice initialization script", 'min_role_id': 10}, # CPU share {'name': "cpu_min", 'description': "Minimum CPU share (ms/s)", 'min_role_id': 10}, {'name': "cpu_share", 'description': "Number of CPU shares", 'min_role_id': 10}, # Bandwidth limits {'name': "net_min", 'description': "Minimum bandwidth (bps)", 'min_role_id': 10}, {'name': "net_max", 'description': "Maximum bandwidth (bps)", 'min_role_id': 10}, {'name': "net_avg", 'description': "Average bandwidth (bps)", 'min_role_id': 10}, {'name': "net_share", 'description': "Number of bandwidth shares", 'min_role_id': 10}, {'name': "net2_min", 'description': "Minimum bandwidth over routes exempt from node bandwidth limits (bps)", 'min_role_id': 10}, {'name': "net2_max", 'description': "Maximum bandwidth over routes exempt from node bandwidth limits (bps)", 'min_role_id': 10}, {'name': "net2_avg", 'description': "Average bandwidth over routes exempt from node bandwidth limits (bps)", 'min_role_id': 10}, {'name': "net2_share", 'description': "Number of bandwidth shares over routes exempt from node bandwidth limits", 'min_role_id': 10}, # Disk quota {'name': "disk_max", 'description': "Disk quota (1k disk blocks)", 'min_role_id': 10}, # Proper operations {'name': "proper_op", 'description': "Proper operation (e.g. bind_socket)", 'min_role_id': 10}, # XXX Required for old Node Manager # Special attributes applicable to Slice Creation Service (pl_conf) slice {'name': "plc_slice_type", 'description': "Type of slice rspec to be created", 'min_role_id': 20}, {'name': "plc_agent_version", 'description': "Version of PLC agent (slice creation service) software to be deployed", 'min_role_id': 10}, {'name': "plc_ticket_pubkey", 'description': "Public key used to verify PLC-signed tickets", 'min_role_id': 10} ] # Get list of existing attribute types attribute_types = GetSliceAttributeTypes() attribute_types = [attribute_type['name'] for attribute_type in attribute_types] # Create/update default slice attribute types for default_attribute_type in default_attribute_types: if default_attribute_type['name'] not in attribute_types: AddSliceAttributeType(default_attribute_type) else: UpdateSliceAttributeType(default_attribute_type['name'], default_attribute_type) # Get contents of SSL public certificate used for signing slice tickets try: plc_ticket_pubkey = "" for line in file(plc_ma_sa['ca_ssl_key_pub']): # Skip comments if line[0:5] != "-----": # XXX The embedded newlines matter, do not strip()! plc_ticket_pubkey += line except: plc_ticket_pubkey = '%KEY%' # Create/update system slices legacy_slices = [ # XXX Required for old Node Manager {'name': "pl_conf", 'description': "PlanetLab Slice Creation Service (SCS)", 'url': url, 'instantiation': "plc-instantiated", # Renew forever 'expires': sys.maxint, 'attributes': [('plc_slice_type', "VServerSlice"), ('plc_agent_version', "1.0"), ('plc_ticket_pubkey', plc_ticket_pubkey)]}, # XXX Required for old Node Manager {'name': "pl_conf_vserverslice", 'description': "Default attributes for vserver slices", 'url': url, 'instantiation': "plc-instantiated", # Renew forever 'expires': sys.maxint, 'attributes': [('cpu_share', "32"), ('plc_slice_type', "VServerSlice"), ('disk_max', "5000000")]}, ] default_slices = [ # PlanetFlow {'name': plc['slice_prefix'] + "_netflow", 'description': "PlanetFlow Traffic Auditing Service", 'url': url, 'instantiation': "plc-instantiated", # Renew forever 'expires': sys.maxint, 'attributes': [('system', "1"), ('vref', "planetflow"), ('proper_op', "open file=/etc/passwd, flags=r"), ('proper_op', "create_socket"), ('proper_op', "bind_socket")]}, ] ### xxx - to review once new node manager rolls out # if PLC_SLICE_PREFIX is left to default - this is meant for the public PL only if plc['slice_prefix'] == 'pl': # create both legacy slices together with netflow through default_slices default_slices += legacy_slices else: # we use another slice prefix : disable legacy slices if already created for legacy_slice in legacy_slices: try: DeleteSlice(legacy_slice['name']) except: pass for default_slice in default_slices: slices = GetSlices([default_slice['name']]) if slices: slice = slices[0] UpdateSlice(slice['slice_id'], default_slice) else: AddSlice(default_slice) slice = GetSlices([default_slice['name']])[0] # Create/update all attributes slice_attributes = [] if slice['slice_attribute_ids']: # Delete unknown attributes for slice_attribute in GetSliceAttributes(slice['slice_attribute_ids']): if (slice_attribute['name'], slice_attribute['value']) \ not in default_slice['attributes']: DeleteSliceAttribute(slice_attribute['slice_attribute_id']) else: slice_attributes.append((slice_attribute['name'], slice_attribute['value'])) for (name, value) in default_slice['attributes']: if (name, value) not in slice_attributes: AddSliceAttribute(slice['name'], name, value) # Load default message templates message_templates = [ {'message_id': 'Verify account', 'subject': "Verify account registration", 'template': """ Please verify that you registered for a %(PLC_NAME)s account with the username %(email)s by visiting: https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/persons/register.php?id=%(person_id)d&key=%(verification_key)s If you did not register for a %(PLC_NAME)s account, please ignore this message, or contact %(PLC_NAME)s Support <%(PLC_MAIL_SUPPORT_ADDRESS)s>. """ }, {'message_id': 'New PI account', 'subject': "New PI account registration from %(first_name)s %(last_name)s <%(email)s> at %(site_name)s", 'template': """ %(first_name)s %(last_name)s <%(email)s> has signed up for a new %(PLC_NAME)s account at %(site_name)s and has requested a PI role. PIs are responsible for enabling user accounts, creating slices, and ensuring that all users abide by the %(PLC_NAME)s Acceptable Use Policy. Only %(PLC_NAME)s administrators may enable new PI accounts. If you are a PI at %(site_name)s, please respond and indicate whether this registration is acceptable. To view the request, visit: https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/persons/index.php?id=%(person_id)d """ }, {'message_id': 'New account', 'subject': "New account registration from %(first_name)s %(last_name)s <%(email)s> at %(site_name)s", 'template': """ %(first_name)s %(last_name)s <%(email)s> has signed up for a new %(PLC_NAME)s account at %(site_name)s and has requested the following roles: %(roles)s. To deny the request or enable the account, visit: https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/persons/index.php?id=%(person_id)d """ }, {'message_id': 'Password reset requested', 'subject': "Password reset requested", 'template': """ Someone has requested that the password of your %(PLC_NAME)s account %(email)s be reset. If this person was you, you may continue with the reset by visiting: https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/persons/reset_password.php?id=%(person_id)d&key=%(verification_key)s If you did not request that your password be reset, please contact %(PLC_NAME)s Support <%(PLC_MAIL_SUPPORT_ADDRESS)s>. Do not quote or otherwise include any of this text in any correspondence. """ }, {'message_id': 'Password reset', 'subject': "Password reset", 'template': """ The password of your %(PLC_NAME)s account %(email)s has been temporarily reset to: %(password)s Please change it at as soon as possible by visiting: https://%(PLC_WWW_HOST)s:%(PLC_WWW_SSL_PORT)d/db/persons/index.php?id=%(person_id)d If you did not request that your password be reset, please contact %(PLC_NAME)s Support <%(PLC_MAIL_SUPPORT_ADDRESS)s>. Do not quote or otherwise include any of this text in any correspondence. """ }, ] for template in message_templates: messages = GetMessages([template['message_id']]) if not messages: AddMessage(template) if __name__ == '__main__': main() # Local variables: # tab-width: 4 # mode: python # End: