Commit fc8f3bc7 authored by Stefano Alberto Russo's avatar Stefano Alberto Russo
Browse files

Added supprt for setting environment variables for containers.

parent c98fbd86
Loading
Loading
Loading
Loading
+48 −6
Original line number Diff line number Diff line
from .models import TaskStatuses, KeyPair, Task, Storage
from .utils import os_shell, get_ssh_access_mode_credentials
from .utils import os_shell, get_ssh_access_mode_credentials, sanitize_container_env_vars
from .exceptions import ErrorMessage, ConsistencyException
from django.conf import settings

@@ -107,6 +107,15 @@ class InternalStandaloneComputingManager(StandaloneComputingManager):
        if not task.requires_proxy and task.password:
            run_command += ' -eAUTH_PASS={} '.format(task.password)

        # Env vars if any
        if task.container.env_vars:
            
            # Sanitize again just in case the DB got somehow compromised:
            env_vars = sanitize_container_env_vars(task.container.env_vars)
            
            for env_var in env_vars:
                run_command += ' -e{}={} '.format(env_var, env_vars[env_var])

        # User data volume
        #run_command += ' -v {}/user-{}:/data'.format(settings.LOCAL_USER_DATA_DIR, task.user.id)

@@ -204,7 +213,18 @@ class SSHStandaloneComputingManager(StandaloneComputingManager, SSHComputingMana
            # Set pass if any
            authstring = ''
            if not task.requires_proxy_auth and task.password:
                authstring = ' export SINGULARITYENV_AUTH_PASS={} && '.format(task.password)
                authstring = ' && export SINGULARITYENV_AUTH_PASS={} '.format(task.password)

            # Env vars if any
            if task.container.env_vars:
                varsstring = ''
                # Sanitize again just in case the DB got somehow compromised:
                env_vars = sanitize_container_env_vars(task.container.env_vars)
                
                for env_var in env_vars:
                    varsstring += ' && export SINGULARITYENV_{}={} '.format(env_var, env_vars[env_var])
            else:
                varsstring = ''
                    
            # Handle storages (binds)
            binds = ''
@@ -241,7 +261,7 @@ class SSHStandaloneComputingManager(StandaloneComputingManager, SSHComputingMana
            run_command  = 'ssh -o LogLevel=ERROR -i {} -4 -o StrictHostKeyChecking=no {}@{} '.format(computing_keys.private_key_file, computing_user, computing_host)
            run_command += '/bin/bash -c \'"rm -rf /tmp/{}_data && mkdir -p /tmp/{}_data/tmp && mkdir -p /tmp/{}_data/home && chmod 700 /tmp/{}_data && '.format(task.uuid, task.uuid, task.uuid, task.uuid) 
            run_command += 'wget {}/api/v1/base/agent/?task_uuid={} -O /tmp/{}_data/agent.py &> /dev/null && export BASE_PORT=\$(python /tmp/{}_data/agent.py 2> /tmp/{}_data/task.log) && '.format(webapp_conn_string, task.uuid, task.uuid, task.uuid, task.uuid)
            run_command += 'export SINGULARITY_NOHTTPS=true && export SINGULARITYENV_BASE_PORT=\$BASE_PORT && {} '.format(authstring)
            run_command += 'export SINGULARITY_NOHTTPS=true && export SINGULARITYENV_BASE_PORT=\$BASE_PORT {} {} &&'.format(authstring, varsstring)
            run_command += 'exec nohup singularity run {} --pid --writable-tmpfs --no-home --home=/home/metauser --workdir /tmp/{}_data/tmp -B/tmp/{}_data/home:/home --containall --cleanenv '.format(binds, task.uuid, task.uuid)
            
            # Container part
@@ -255,6 +275,17 @@ class SSHStandaloneComputingManager(StandaloneComputingManager, SSHComputingMana
            if not task.requires_proxy_auth and task.password:
                authstring = ' -e AUTH_PASS={} '.format(task.password)

            # Env vars if any
            if task.container.env_vars:
                varsstring = ''
                # Sanitize again just in case the DB got somehow compromised:
                env_vars = sanitize_container_env_vars(task.container.env_vars)
                
                for env_var in env_vars:
                    varsstring += ' -e {}={} '.format(env_var, env_vars[env_var])
            else:
                varsstring = ''
         
            # Handle storages (binds)
            binds = ''
            storages = Storage.objects.filter(computing=self.computing)
@@ -293,7 +324,7 @@ class SSHStandaloneComputingManager(StandaloneComputingManager, SSHComputingMana
            run_command  = 'ssh -o LogLevel=ERROR -i {} -4 -o StrictHostKeyChecking=no {}@{} '.format(computing_keys.private_key_file, computing_user, computing_host)
            run_command += '/bin/bash -c \'"rm -rf /tmp/{}_data && mkdir /tmp/{}_data && chmod 700 /tmp/{}_data && '.format(task.uuid, task.uuid, task.uuid) 
            run_command += 'wget {}/api/v1/base/agent/?task_uuid={} -O /tmp/{}_data/agent.py &> /dev/null && export TASK_PORT=\$(python /tmp/{}_data/agent.py 2> /tmp/{}_data/task.log) && '.format(webapp_conn_string, task.uuid, task.uuid, task.uuid, task.uuid)
            run_command += '{} {} run -p \$TASK_PORT:{} {} {} '.format(prefix, container_engine, task.container.interface_port, authstring, binds)        
            run_command += '{} {} run -p \$TASK_PORT:{} {} {} {} '.format(prefix, container_engine, task.container.interface_port, authstring, varsstring, binds)        
            if container_engine == 'podman':
                run_command += '--network=private --uts=private '
            #run_command += '-d -t {}/{}:{}'.format(task.container.registry, task.container.image_name, task.container.image_tag)
@@ -435,7 +466,18 @@ class SlurmSSHClusterComputingManager(ClusterComputingManager, SSHComputingManag
            # Set pass if any
            authstring = ''
            if not task.requires_proxy_auth and task.password:
                authstring = ' export SINGULARITYENV_AUTH_PASS={} && '.format(task.password)
                authstring = ' && export SINGULARITYENV_AUTH_PASS={} '.format(task.password)

            # Env vars if any
            if task.container.env_vars:
                varsstring = ''
                # Sanitize again just in case the DB got somehow compromised:
                env_vars = sanitize_container_env_vars(task.container.env_vars)
                
                for env_var in env_vars:
                    varsstring += ' && export SINGULARITYENV_{}={} '.format(env_var, env_vars[env_var])
            else:
                varsstring = ''
        
            # Handle storages (binds)
            binds = ''
@@ -471,7 +513,7 @@ class SlurmSSHClusterComputingManager(ClusterComputingManager, SSHComputingManag

            run_command = 'ssh -o LogLevel=ERROR -i {} -4 -o StrictHostKeyChecking=no {}@{} '.format(computing_keys.private_key_file, computing_user, computing_host)
            run_command += '\'bash -c "echo \\"#!/bin/bash\nwget {}/api/v1/base/agent/?task_uuid={} -O \$HOME/agent_{}.py &> \$HOME/{}.log && export BASE_PORT=\\\\\\$(python \$HOME/agent_{}.py 2> \$HOME/{}.log) && '.format(webapp_conn_string, task.uuid, task.uuid, task.uuid, task.uuid, task.uuid)
            run_command += 'export SINGULARITY_NOHTTPS=true && export SINGULARITYENV_BASE_PORT=\\\\\\$BASE_PORT && {} '.format(authstring)
            run_command += 'export SINGULARITY_NOHTTPS=true && export SINGULARITYENV_BASE_PORT=\\\\\\$BASE_PORT {} {} && '.format(authstring, varsstring)
            run_command += 'rm -rf /tmp/{}_data && mkdir -p /tmp/{}_data/tmp &>> \$HOME/{}.log && mkdir -p /tmp/{}_data/home &>> \$HOME/{}.log && chmod 700 /tmp/{}_data && '.format(task.uuid, task.uuid, task.uuid, task.uuid, task.uuid, task.uuid)
            run_command += 'exec nohup singularity run {} --pid --writable-tmpfs --no-home --home=/home/metauser --workdir /tmp/{}_data/tmp -B/tmp/{}_data/home:/home --containall --cleanenv '.format(binds, task.uuid, task.uuid)
            
+25 −0
Original line number Diff line number Diff line
# Generated by Django 2.2.1 on 2022-01-16 18:40

from django.conf import settings
from django.db import migrations

# Load database-dependent JSON field
if 'sqlite' in settings.DATABASES['default']['ENGINE']:
    from rosetta.core_app.fields import JSONField
else:
    from django.contrib.postgres.fields import JSONField


class Migration(migrations.Migration):

    dependencies = [
        ('core_app', '0030_auto_20211218_2355'),
    ]

    operations = [
        migrations.AddField(
            model_name='container',
            name='env_vars',
            field=JSONField(blank=True, null=True, verbose_name='Container env vars'),
        ),
    ]
+3 −0
Original line number Diff line number Diff line
@@ -141,6 +141,9 @@ class Container(models.Model):
    supports_interface_auth = models.BooleanField('Supports interface auth', default=False) # AUTH_USER / AUTH_PASS
    interface_auth_user = models.CharField('Interface auth fixed user if any', max_length=36, blank=True, null=True)

    # Env vars for some container control
    env_vars = JSONField('Container env vars', blank=True, null=True)

    class Meta:
        ordering = ['name']

+7 −0
Original line number Diff line number Diff line
@@ -135,6 +135,13 @@
            </td>
           </tr>

           <tr>
            <td><b>Environment variables</b></td>
            <td>
<textarea name="container_env_vars" rows="2" cols="22" placeholder='JSON format: {"VAR"="VALUE"}'></textarea>
            </td>
           </tr>

          </table>
          </div>
          
+6 −0
Original line number Diff line number Diff line
@@ -104,6 +104,12 @@
         {% endif %}        </td>
       </tr>

       {% if container.env_vars %}
       <tr>
        <td><b>Env vars</b></td>
        <td><pre>{{container.env_vars}}</pre></td>
       </tr>
       {% endif %}
       
       {% if container.user %}
       <tr>
Loading