示例#1
0
def housekeeping():
    """ calls housekeep for each manager. is run periodically.
    """
    token = get_token()
    logger.info('provisioning plugins queried from worker')
    mgr = get_provisioning_manager()
    mgr.map_method(mgr.names(), 'housekeep', token)
示例#2
0
def proxy_add_route(route_key, target, options):
    """ adds a route to nginx configs for access to e.g. a container
    """
    logger.info('proxy_add_route(%s, %s)' % (route_key, target))

    # generate a location snippet for nginx proxy config
    # see https://support.rstudio.com/hc/en-us/articles/200552326-Running-with-a-Proxy

    config = [
        'location /notebooks/%s/ {' % (route_key),
        'proxy_pass %s;' % (target), 'proxy_http_version 1.1;',
        'proxy_set_header Upgrade $http_upgrade;',
        'proxy_set_header Connection "upgrade";', 'proxy_read_timeout 86400;'
    ]

    dynamic_config = get_dynamic_config()
    external_https_port = dynamic_config['EXTERNAL_HTTPS_PORT']
    if 'proxy_rewrite' in options:
        config.append('rewrite ^/notebooks/%s/(.*)$ /$1 break;' % (route_key))
    if 'proxy_redirect' in options:
        config.append('proxy_redirect %s $scheme://$host:%d/notebooks/%s;' %
                      (target, external_https_port, route_key))
    if 'set_host_header' in options:
        config.append('proxy_set_header Host $host;')
    if 'bypass_token_authentication' in options:
        instance_id = options['bypass_token_authentication']
        config.append('proxy_set_header Authorization "token %s";' %
                      (instance_id))

    config.append('}')
    path = '%s/route_key-%s' % (RUNTIME_PATH, route_key)
    with open(path, 'w') as f:
        f.write('\n'.join(config))

    refresh_nginx_config()
示例#3
0
def send_mails(users, text=None):
    """ ToDo: document. apparently sends activation emails.
    """
    dynamic_config = get_dynamic_config()
    j2_env = jinja2.Environment(
        loader=jinja2.PackageLoader('pebbles', 'templates'))
    base_url = dynamic_config['BASE_URL'].strip('/')
    for email, token, user_active in users:
        if text is None:
            activation_url = '%s/#/activate/%s' % (base_url, token)
            msg = MIMEText(
                j2_env.get_template('invitation.txt').render(
                    activation_link=activation_url,
                    instance_name=dynamic_config['INSTALLATION_NAME'],
                    instance_description=dynamic_config[
                        'INSTALLATION_DESCRIPTION'],
                    user_active=user_active))
            subject = '%s account activation' if not user_active else '%s password reset'
            msg['Subject'] = subject % dynamic_config['INSTALLATION_NAME']
        else:
            msg = MIMEText(text['message'])
            subject = text['subject'] + " - %s"
            msg['Subject'] = subject % dynamic_config['INSTALLATION_NAME']
        msg['To'] = email
        msg['From'] = dynamic_config['SENDER_EMAIL']
        logger.info(msg)

        if not dynamic_config['MAIL_SUPPRESS_SEND']:
            s = smtplib.SMTP(dynamic_config['MAIL_SERVER'])
            if dynamic_config['MAIL_USE_TLS']:
                s.starttls()
            s.sendmail(msg['From'], [msg['To']], msg.as_string())
            s.quit()
        else:
            logger.info('Mail sending suppressed in config')
示例#4
0
def send_mails(users):
    """ ToDo: document. apparently sends activation emails.
    """
    config = get_config()
    j2_env = jinja2.Environment(
        loader=jinja2.PackageLoader('pebbles', 'templates'))
    base_url = config['BASE_URL'].strip('/')
    for email, token in users:
        activation_url = '%s/#/activate/%s' % (base_url, token)
        msg = MIMEText(
            j2_env.get_template('invitation.txt').render(
                activation_link=activation_url))
        msg['Subject'] = 'Pebbles account activation'
        msg['To'] = email
        msg['From'] = config['SENDER_EMAIL']
        logger.info(msg)

        if not config['MAIL_SUPPRESS_SEND']:
            s = smtplib.SMTP(config['MAIL_SERVER'])
            if config['MAIL_USE_TLS']:
                s.starttls()
            s.sendmail(msg['From'], [msg['To']], msg.as_string())
            s.quit()
        else:
            logger.info('Mail sending suppressed in config')
示例#5
0
def update_user_connectivity(instance_id):
    """ updates the connectivity for a single instance.
    """
    logger.info('updating connectivity for instance %s' % instance_id)
    token = get_token()
    mgr = get_provisioning_manager()
    plugin = get_provisioning_type(token, instance_id)
    mgr.map_method([plugin], 'update_connectivity', token, instance_id)
    logger.info('update connectivity for instance %s ready' % instance_id)
示例#6
0
def run_update(instance_id):
    """ calls the update method for the manager of a single instance.
    """
    logger.info('update triggered for %s' % instance_id)
    token = get_token()
    mgr = get_provisioning_manager()
    plugin = get_provisioning_type(token, instance_id)
    mgr.map_method([plugin], 'update', token, instance_id)

    logger.info('update done, notifying server')
示例#7
0
def proxy_remove_route(route_key):
    """ removes a route from nginx config e.g. when removing a resource.
    """
    logger.info('proxy_remove_route(%s)' % route_key)

    path = '%s/route_key-%s' % (RUNTIME_PATH, route_key)
    if os.path.exists(path):
        os.remove(path)
    else:
        logger.info('proxy_remove_route(): no such file')

    refresh_nginx_config()
示例#8
0
def periodic_update():
    """ Runs periodic updates.

    In particular sets old instances up for deprovisioning after they are past
    their maximum_lifetime and sets instances up for up updates.

    Both deletion and update events are not guaranteed to take place
    immediately. If there are more than 10 instances a random sample of 10
    updates and deletions will take place to ensure task is safe to run and
    won't slow down other tasks.
    """
    token = get_token()
    pbclient = PBClient(token,
                        local_config['INTERNAL_API_BASE_URL'],
                        ssl_verify=False)
    instances = pbclient.get_instances()

    deprovision_list = []
    update_list = []
    for instance in instances:
        logger.debug('checking instance for actions %s' % instance['name'])
        deprovision_required = False
        if instance.get('state') in [Instance.STATE_RUNNING]:
            if not instance.get('lifetime_left') and instance.get(
                    'maximum_lifetime'):
                deprovision_required = True

            if deprovision_required:
                deprovision_list.append(instance)

        elif instance.get('state') not in [Instance.STATE_FAILED]:
            update_list.append(instance)

    # ToDo: refactor magic number to variable
    if len(deprovision_list) > 10:
        deprovision_list = random.sample(deprovision_list, 10)
    for instance in deprovision_list:
        logger.info(
            'deprovisioning triggered for %s (reason: maximum lifetime exceeded)'
            % instance.get('id'))
        pbclient.do_instance_patch(instance['id'], {'to_be_deleted': True})
        run_update.delay(instance.get('id'))

    if len(update_list) > 10:
        update_list = random.sample(update_list, 10)
    for instance in update_list:
        run_update.delay(instance.get('id'))
示例#9
0
def publish_plugins():
    """ ToDo: document.
    """
    logger.info('provisioning plugins queried from worker')
    token = get_token()
    mgr = get_provisioning_manager()
    for plugin in mgr.names():
        payload = {'plugin': plugin}
        res = mgr.map_method([plugin], 'get_configuration')
        if not len(res):
            logger.warn('plugin returned empty configuration: %s' % plugin)
            continue
        config = res[0]

        if not config:
            logger.warn('No config for %s obtained' % plugin)
            continue

        for key in ('schema', 'form', 'model'):
            payload[key] = json.dumps(config.get(key, {}))

        do_post(token, 'plugins', payload)