diff --git a/images/webapp/code/rosetta/base_app/templates/add_container.html b/images/webapp/code/rosetta/base_app/templates/add_container.html index b4758e82b56fac603768f7915e6d039fbaa76b95..8f9af73bfcbffe4b94c35b588b8d3208b0217a81 100644 --- a/images/webapp/code/rosetta/base_app/templates/add_container.html +++ b/images/webapp/code/rosetta/base_app/templates/add_container.html @@ -34,9 +34,9 @@ <tr> <td><b>Registry</b></td><td> <select name="container_registry" > - <option value="docker_local" selected>Local</option> + <option value="docker_local" selected>Docker Local</option> <option value="docker_hub">Docker Hub</option> - <option value="singularityhub">Singularity Hub</option> + <option value="singularity_hub">Singularity Hub</option> </select> </td> </tr> diff --git a/images/webapp/code/rosetta/base_app/templates/components/container.html b/images/webapp/code/rosetta/base_app/templates/components/container.html new file mode 100644 index 0000000000000000000000000000000000000000..10d26815d04bb90d033cba99d16af9b733f55ebd --- /dev/null +++ b/images/webapp/code/rosetta/base_app/templates/components/container.html @@ -0,0 +1,40 @@ + <table class="dashboard"> + + <tr> + <td><b>ID</b></td> + <td><a href="?uuid={{ container.uuid }}">{{ container.id }}</a></td> + </tr> + + <tr> + <td><b>Image</b></td> + <td>{{ container.image }}</td> + </tr> + + <tr> + <td><b>Type</b></td> + <td>{{ container.type }}</td> + </tr> + + <tr> + <td><b>Owner</b></td> + <td>{% if container.user %}{{ container.user }}{% else %}Platform{% endif %}</td> + </tr> + + <tr> + <td><b>Registry</b></td> + <td>{{ container.registry }}</td> + </tr> + + <tr> + <td><b>Service port(s)</b></td> + <td>{{ container.service_ports}}</td> + </tr> + + {% if container.user %} + <tr> + <td><b>Operations</b></td> + <td><a href="?action=delete&uuid={{ container.uuid }}">Delete</a></td> + </tr> + {% endif %} + </table> + <br/> \ No newline at end of file diff --git a/images/webapp/code/rosetta/base_app/templates/components/task.html b/images/webapp/code/rosetta/base_app/templates/components/task.html new file mode 100644 index 0000000000000000000000000000000000000000..a075868e6c061734945b3491bec641db37819edc --- /dev/null +++ b/images/webapp/code/rosetta/base_app/templates/components/task.html @@ -0,0 +1,77 @@ + + <table class="dashboard"> + + <tr> + <td><b>ID</b></td> + <td><a href="?uuid={{ task.uuid }}">{{ task.id }}</a></td> + </tr> + + <tr> + <td><b>Name</b></td> + <td>{{ task.name }}</td> + </tr> + + <tr> + <td><b>Container</b></td> + <td><a href="/containers/?uuid={{ task.container.uuid }}">{{ task.container.image }}</a></td> + </tr> + + <tr> + <td><b>Status</b></td> + <td>{{ task.status }}</td> + </tr> + + <tr> + <td><b>Created at</b></td> + <td>{{ task.created }}</td> + </tr> + + <!-- <tr> + <td><b>Task pid</b></td> + <td>{{ task.pid}}</td> + </tr> --> + + <tr> + <td><b>IP</b></td> + <td>{{ task.ip}}</td> + </tr> + + <tr> + <td><b>Port</b></td> + <td>{{ task.port }}</td> + </tr> + + <tr> + <td><b>Task tunnel port</b></td> + <td>{{ task.tunnel_port }}</td> + </tr> + + <tr> + <td><b>Operations</b></td> + + <td> + {% if task.status == "running" %} + <a href="?uuid={{task.uuid}}&action=stop&details={{details}}">Stop</a> | + {% else %} + <!-- <a href=?uuid={{task.uuid}}&action=start>Start</a> | --> + <font color="#c0c0c0">Stop</font> | + + {% endif %} + {% if task.status == "exited" or task.status == "stopped" %} + <a href="?uuid={{task.uuid}}&action=delete&details=False">Delete</a> + {% else %} + <font color="#c0c0c0">Delete</font> + {% endif %} + {% if task.status == "running" %} + | <a href="?uuid={{task.uuid}}&action=connect">Connect</a> + | <a href="/task_log/?uuid={{task.uuid}}&action=viewlog">View Log</a> + {% else %} + | <font color="#c0c0c0">Connect</font> + | <font color="#c0c0c0">View Log</font> + {% endif%} + </td> + + </tr> + + </table> + <br/> \ No newline at end of file diff --git a/images/webapp/code/rosetta/base_app/templates/containers.html b/images/webapp/code/rosetta/base_app/templates/containers.html index f94eb33d8d8ba9cb66bcf71ca7c6367ca6b052e4..750f3f4b7a4e035ed8f051f40393b86e39082646 100644 --- a/images/webapp/code/rosetta/base_app/templates/containers.html +++ b/images/webapp/code/rosetta/base_app/templates/containers.html @@ -8,125 +8,27 @@ <div class="container"> <div class="dashboard"> <div class="span8 offset2"> - <h1><a href="/containers">Container List</a> {% if data.container %}> {{ data.container.id }} {% endif %} </h1> + + {% if data.container %} + <h1><a href="/containers">Container List</a> > {{ data.container.id }} </h1> + {% else %} + <h1>Container List</h1> + {% endif %} + <hr/> {% if data.container %} - <table class="dashboard"> - - <tr> - <td><b>ID</b></td> - <td>{{ data.container.id }}</td> - </tr> - - <tr> - <td><b>Image</b></td> - <td>{{ data.container.image }}</td> - </tr> - - <tr> - <td><b>Type</b></td> - <td>{{ data.container.type }}</td> - </tr> - - <tr> - <td><b>Owner</b></td> - <td>{% if data.container.user %}{{data.container.user}}{% else %}Platform{% endif %}</td> - </tr> - - <tr> - <td><b>Registry</b></td> - <td>{{ data.container.registry }}</td> - </tr> - - <tr> - <td><b>Service port(s)</b></td> - <td>{{ data.container.service_ports}}</td> - </tr> - - </table> - <br /> - + {% include "components/container.html" with container=data.container %} {% else %} {% for container in data.platform_containers %} - - <table class="dashboard"> - - <tr> - <td><b>ID</b></td> - <td><a href="?uuid={{ container.uuid }}">{{ container.id }}</a></td> - </tr> - - <tr> - <td><b>Image</b></td> - <td>{{ container.image }}</td> - </tr> - - <tr> - <td><b>Type</b></td> - <td>{{ container.type }}</td> - </tr> - - <tr> - <td><b>Owner</b></td> - <td>Platform</td> - </tr> - - <tr> - <td><b>Registry</b></td> - <td>{{ container.registry }}</td> - </tr> - - <tr> - <td><b>Service port(s)</b></td> - <td>{{ container.service_ports}}</td> - </tr> - - </table> + {% include "components/container.html" with container=container %} <br /> {% endfor %} {% for container in data.user_containers %} - <table class="dashboard"> - - <tr> - <td><b>ID</b></td> - <td><a href="?uuid={{ container.uuid }}">{{ container.id }}</a></td> - </tr> - - <tr> - <td><b>Image</b></td> - <td>{{ container.image }}</td> - </tr> - - <tr> - <td><b>Type</b></td> - <td>{{ container.type }}</td> - </tr> - - <tr> - <td><b>Owner</b></td> - <td>{{container.user}}</td> - </tr> - - <tr> - <td><b>Registry</b></td> - <td>{{ container.registry }}</td> - </tr> - - <tr> - <td><b>Service port(s)</b></td> - <td>{{ container.service_ports}}</td> - </tr> - - <tr> - <td><b>Operations</b></td> - <td><a href="?action=delete&uuid={{ container.uuid }}">Delete</a></td> - </tr> - - </table> + {% include "components/container.html" with container=container %} <br /> {% endfor %} diff --git a/images/webapp/code/rosetta/base_app/templates/tasks.html b/images/webapp/code/rosetta/base_app/templates/tasks.html index f517882c17d3ece76d8ecf42cb80d0d029cb9e88..65696bc78e88f626f00dcdab85720be7a66a40dd 100644 --- a/images/webapp/code/rosetta/base_app/templates/tasks.html +++ b/images/webapp/code/rosetta/base_app/templates/tasks.html @@ -8,95 +8,25 @@ <div class="container"> <div class="dashboard"> <div class="span8 offset2"> + + + {% if data.task %} + <h1><a href="/tasks">Task List</a> > {{ data.task.id }} </h1> + {% else %} <h1>Task List</h1> + {% endif %} <hr> - - - {% for task in data.tasks %} - <table class="dashboard"> - - <tr> - <td><b>ID</b></td> - <td>{{ task.id }}</td> - </tr> - - <tr> - <td><b>Name</b></td> - <td>{{ task.name }}</td> - </tr> - - <tr> - <td><b>Container</b></td> - <td><a href="">{{ task.container.image }}</a></td> - </tr> - - <tr> - <td><b>Status</b></td> - <td>{{ task.status }}</td> - </tr> - - <tr> - <td><b>Created at</b></td> - <td>{{ task.created }}</td> - </tr> - - <!-- <tr> - <td><b>Task pid</b></td> - <td>{{ task.pid}}</td> - </tr> --> - - <tr> - <td><b>IP</b></td> - <td>{{ task.ip}}</td> - </tr> - - <tr> - <td><b>Port</b></td> - <td>{{ task.port }}</td> - </tr> - - <tr> - <td><b>Task tunnel port</b></td> - <td>{{ task.tunnel_port }}</td> - </tr> + {% if data.task %} + {% include "components/task.html" with task=data.task details=True %} + {% else %} + {% for task in data.tasks %} + {% include "components/task.html" with task=task %} + {% endfor %} + <br /> + <a href="/create_task">Add new...</a> + {% endif %} - <tr> - <td><b>Operations</b></td> - - <td> - {% if task.status == "running" %} - <a href=?uuid={{task.uuid}}&action=stop>Stop</a> | - {% else %} - <!-- <a href=?uuid={{task.uuid}}&action=start>Start</a> | --> - <font color="#c0c0c0">Stop</font> | - - {% endif %} - {% if task.status == "exited" or task.status == "stopped" %} - <a href=?uuid={{task.uuid}}&action=delete>Delete</a> - {% else %} - <font color="#c0c0c0">Delete</font> - {% endif %} - {% if task.status == "running" %} - | <a href=?uuid={{task.uuid}}&action=connect>Connect</a> - | <a href=/task_log/?uuid={{task.uuid}}&action=viewlog>View Log</a> - {% else %} - | <font color="#c0c0c0">Connect</font> - | <font color="#c0c0c0">View Log</font> - {% endif%} - </td> - - </tr> - - </table> - <br /> - {% endfor %} - - - <br /> - {% if not data.sid %} - <a href="/create_task">Add new...</a> - {% endif %} <br/> <br/> <br/> diff --git a/images/webapp/code/rosetta/base_app/views.py b/images/webapp/code/rosetta/base_app/views.py index 8e62bb5b2ace5c80dfb454e098f8a60ee0617fb6..964971e482eae8ffb1db6619b20ac9c08517ff83 100644 --- a/images/webapp/code/rosetta/base_app/views.py +++ b/images/webapp/code/rosetta/base_app/views.py @@ -21,7 +21,7 @@ from django.contrib.auth import update_session_auth_hash # Project imports from .models import Profile, LoginToken, Task, TaskStatuses, Container -from .utils import send_email, format_exception, random_username, log_user_activity, timezonize, os_shell +from .utils import send_email, format_exception, random_username, log_user_activity, timezonize, os_shell, booleanize # Setup logging import logging @@ -32,7 +32,9 @@ from .exceptions import ErrorMessage, ConsistencyException # Conf SUPPORTED_CONTAINER_TYPES = ['docker', 'singularity'] -SUPPORTED_REGISTRIES = ['docker_local', 'docker_hub', 'signularity_hub'] +SUPPORTED_REGISTRIES = ['docker_local', 'docker_hub', 'singularity_hub'] +UNSUPPORTED_TYPES_VS_REGISTRIES = ['docker:singularity_hub'] + TASK_DATA_DIR = "/data" #========================= @@ -381,161 +383,186 @@ def tasks(request): data['title'] = 'Tasks' # Get action if any - action = request.GET.get('action', None) - uuid = request.GET.get('uuid', None) - + action = request.GET.get('action', None) + uuid = request.GET.get('uuid', None) + details = booleanize(request.GET.get('details', None)) + # Setting var standby_supported = False - # Perform actions if required: - if action and uuid: - - # Get the task (raises if none available including no permission) - task = Task.objects.get(user=request.user, uuid=uuid) + # Do we have to operate on a specific task? + if uuid: - if action=='delete': - if task.status not in [TaskStatuses.stopped, TaskStatuses.exited]: - data['error'] = 'Can delete only tasks in the stopped state' - return render(request, 'error.html', {'data': data}) + try: + + # Get the task (raises if none available including no permission) try: - # Get the task (raises if none available including no permission) task = Task.objects.get(user=request.user, uuid=uuid) + except Task.DoesNotExist: + raise ErrorMessage('Task does not exists or no access rights') + data['task'] = task + + #---------------- + # Task actions + #---------------- - # Delete - task.delete() - - except Exception as e: - data['error'] = 'Error in deleting the task' - logger.error('Error in deleting task with uuid="{}": "{}"'.format(uuid, e)) - return render(request, 'error.html', {'data': data}) - - elif action=='stop': # or delete,a and if delete also remove object - try: - - if task.compute == 'local': - - # Delete the Docker container - if standby_supported: - stop_command = 'sudo docker stop {}'.format(task.tid) + if action=='delete': + if task.status not in [TaskStatuses.stopped, TaskStatuses.exited]: + data['error'] = 'Can delete only tasks in the stopped state' + return render(request, 'error.html', {'data': data}) + try: + # Get the task (raises if none available including no permission) + task = Task.objects.get(user=request.user, uuid=uuid) + + # Delete + task.delete() + + # Unset task + data['task'] = None + + except Exception as e: + data['error'] = 'Error in deleting the task' + logger.error('Error in deleting task with uuid="{}": "{}"'.format(uuid, e)) + return render(request, 'error.html', {'data': data}) + + elif action=='stop': # or delete,a and if delete also remove object + try: + if task.compute == 'local': + + # Delete the Docker container + if standby_supported: + stop_command = 'sudo docker stop {}'.format(task.tid) + else: + stop_command = 'sudo docker stop {} && sudo docker rm {}'.format(task.tid,task.tid) + + out = os_shell(stop_command, capture=True) + if out.exit_code != 0: + raise Exception(out.stderr) + + elif task.compute == 'demoremote': + + # Stop the task remotely + stop_command = 'ssh -4 -o StrictHostKeyChecking=no slurmclusterworker-one "kill -9 {}"'.format(task.pid) + logger.debug(stop_command) + out = os_shell(stop_command, capture=True) + if out.exit_code != 0: + if not 'No such process' in out.stderr: + raise Exception(out.stderr) + else: - stop_command = 'sudo docker stop {} && sudo docker rm {}'.format(task.tid,task.tid) - - out = os_shell(stop_command, capture=True) - if out.exit_code != 0: - raise Exception(out.stderr) - - elif task.compute == 'demoremote': - - # Stop the task remotely - stop_command = 'ssh -4 -o StrictHostKeyChecking=no slurmclusterworker-one "kill -9 {}"'.format(task.pid) - logger.debug(stop_command) - out = os_shell(stop_command, capture=True) - if out.exit_code != 0: - if not 'No such process' in out.stderr: + data['error']= 'Don\'t know how to stop tasks on "{}" compute resource.'.format(task.compute) + return render(request, 'error.html', {'data': data}) + + # Ok, save status as deleted + task.status = 'stopped' + task.save() + + # Check if the tunnel is active and if so kill it + logger.debug('Checking if task "{}" has a running tunnel'.format(task.tid)) + check_command = 'ps -ef | grep ":'+str(task.tunnel_port)+':'+str(task.ip)+':'+str(task.port)+'" | grep -v grep | awk \'{print $2}\'' + logger.debug(check_command) + out = os_shell(check_command, capture=True) + logger.debug(out) + if out.exit_code == 0: + logger.debug('Task "{}" has a running tunnel, killing it'.format(task.tid)) + tunnel_pid = out.stdout + # Kill Tunnel command + kill_tunnel_command= 'kill -9 {}'.format(tunnel_pid) + + # Log + logger.debug('Killing tunnel with command: {}'.format(kill_tunnel_command)) + + # Execute + os_shell(kill_tunnel_command, capture=True) + if out.exit_code != 0: raise Exception(out.stderr) - - else: - data['error']= 'Don\'t know how to stop tasks on "{}" compute resource.'.format(task.compute) + + except Exception as e: + data['error'] = 'Error in stopping the task' + logger.error('Error in stopping task with uuid="{}": "{}"'.format(uuid, e)) return render(request, 'error.html', {'data': data}) - - # Ok, save status as deleted - task.status = 'stopped' - task.save() - - # Check if the tunnel is active and if so kill it - logger.debug('Checking if task "{}" has a running tunnel'.format(task.tid)) - check_command = 'ps -ef | grep ":'+str(task.tunnel_port)+':'+str(task.ip)+':'+str(task.port)+'" | grep -v grep | awk \'{print $2}\'' - logger.debug(check_command) - out = os_shell(check_command, capture=True) - logger.debug(out) - if out.exit_code == 0: - logger.debug('Task "{}" has a running tunnel, killing it'.format(task.tid)) - tunnel_pid = out.stdout - # Kill Tunnel command - kill_tunnel_command= 'kill -9 {}'.format(tunnel_pid) - - # Log - logger.debug('Killing tunnel with command: {}'.format(kill_tunnel_command)) - - # Execute - os_shell(kill_tunnel_command, capture=True) - if out.exit_code != 0: - raise Exception(out.stderr) - - except Exception as e: - data['error'] = 'Error in stopping the task' - logger.error('Error in stopping task with uuid="{}": "{}"'.format(uuid, e)) - return render(request, 'error.html', {'data': data}) - - elif action=='connect': - - # Get the task (raises if none available including no permission) - task = Task.objects.get(user=request.user, uuid=uuid) - - # Create task tunnel - if task.compute in ['local', 'demoremote']: - - # If there is no tunnel port allocated yet, find one - if not task.tunnel_port: - - # Get a free port fot the tunnel: - allocated_tunnel_ports = [] - for other_task in Task.objects.all(): - if other_task.tunnel_port and not other_task.status in [TaskStatuses.exited, TaskStatuses.stopped]: - allocated_tunnel_ports.append(other_task.tunnel_port) - - for port in range(7000, 7006): - if not port in allocated_tunnel_ports: - tunnel_port = port - break - if not tunnel_port: - logger.error('Cannot find a free port for the tunnel for task "{}"'.format(task.tid)) - raise ErrorMessage('Cannot find a free port for the tunnel to the task') - - task.tunnel_port = tunnel_port - task.save() - - - # Check if the tunnel is active and if not create it - logger.debug('Checking if task "{}" has a running tunnel'.format(task.tid)) - - out = os_shell('ps -ef | grep ":{}:{}:{}" | grep -v grep'.format(task.tunnel_port, task.ip, task.port), capture=True) - - if out.exit_code == 0: - logger.debug('Task "{}" has a running tunnel, using it'.format(task.tid)) + + elif action=='connect': + + # Create task tunnel + if task.compute in ['local', 'demoremote']: + + # If there is no tunnel port allocated yet, find one + if not task.tunnel_port: + + # Get a free port fot the tunnel: + allocated_tunnel_ports = [] + for other_task in Task.objects.all(): + if other_task.tunnel_port and not other_task.status in [TaskStatuses.exited, TaskStatuses.stopped]: + allocated_tunnel_ports.append(other_task.tunnel_port) + + for port in range(7000, 7006): + if not port in allocated_tunnel_ports: + tunnel_port = port + break + if not tunnel_port: + logger.error('Cannot find a free port for the tunnel for task "{}"'.format(task.tid)) + raise ErrorMessage('Cannot find a free port for the tunnel to the task') + + task.tunnel_port = tunnel_port + task.save() + + + # Check if the tunnel is active and if not create it + logger.debug('Checking if task "{}" has a running tunnel'.format(task.tid)) + + out = os_shell('ps -ef | grep ":{}:{}:{}" | grep -v grep'.format(task.tunnel_port, task.ip, task.port), capture=True) + + if out.exit_code == 0: + logger.debug('Task "{}" has a running tunnel, using it'.format(task.tid)) + else: + logger.debug('Task "{}" has no running tunnel, creating it'.format(task.tid)) + + # Tunnel command + tunnel_command= 'ssh -4 -o StrictHostKeyChecking=no -nNT -L 0.0.0.0:{}:{}:{} localhost & '.format(task.tunnel_port, task.ip, task.port) + background_tunnel_command = 'nohup {} >/dev/null 2>&1 &'.format(tunnel_command) + + # Log + logger.debug('Opening tunnel with command: {}'.format(background_tunnel_command)) + + # Execute + subprocess.Popen(background_tunnel_command, shell=True) + else: - logger.debug('Task "{}" has no running tunnel, creating it'.format(task.tid)) - - # Tunnel command - tunnel_command= 'ssh -4 -o StrictHostKeyChecking=no -nNT -L 0.0.0.0:{}:{}:{} localhost & '.format(task.tunnel_port, task.ip, task.port) - background_tunnel_command = 'nohup {} >/dev/null 2>&1 &'.format(tunnel_command) - - # Log - logger.debug('Opening tunnel with command: {}'.format(background_tunnel_command)) - - # Execute - subprocess.Popen(background_tunnel_command, shell=True) + raise ErrorMessage('Connecting to tasks on compute "{}" is not supported yet'.format(task.compute)) + + # Ok, now redirect to the task through the tunnel + from django.shortcuts import redirect + return redirect('http://localhost:{}'.format(task.tunnel_port)) - else: - raise ErrorMessage('Connecting to tasks on compute "{}" is not supported yet'.format(task.compute)) + except Exception as e: + data['error'] = 'Error in getting the task or performing the required action' + logger.error('Error in getting the task with uuid="{}" or performing the required action: "{}"'.format(uuid, e)) + return render(request, 'error.html', {'data': data}) - # Ok, now redirect to the task through the tunnel - from django.shortcuts import redirect - return redirect('http://localhost:{}'.format(task.tunnel_port)) - # Get all tasks - try: - tasks = Task.objects.filter(user=request.user).order_by('created') - except Exception as e: - data['error'] = 'Error in getting Tasks info' - logger.error('Error in getting Virtual Devices: "{}"'.format(e)) - return render(request, 'error.html', {'data': data}) + # Do we have to list all the tasks? + if not uuid or (uuid and not details): - # Update task statuses - for task in tasks: - task.update_status() - - data['tasks'] = tasks + #---------------- + # Task list + #---------------- + + # Get all tasks + try: + tasks = Task.objects.filter(user=request.user).order_by('created') + except Exception as e: + data['error'] = 'Error in getting Tasks info' + logger.error('Error in getting Virtual Devices: "{}"'.format(e)) + return render(request, 'error.html', {'data': data}) + + # Update task statuses + for task in tasks: + task.update_status() + + # Set task and tasks variables + data['task'] = None + data['tasks'] = tasks return render(request, 'tasks.html', {'data': data}) @@ -719,14 +746,14 @@ def task_log(request): if task.compute == 'local': - raise NotImplementedError('Not yet') - # View the Docker container log (attach) - #view_log_command = 'sudo docker stop {} && sudo docker rm {}'.format(task.tid,task.tid) - - #out = os_shell(view_log_command, capture=True) - #if out.exit_code != 0: - # raise Exception(out.stderr) + view_log_command = 'sudo docker logs {}'.format(task.tid,) + logger.debug(view_log_command) + out = os_shell(view_log_command, capture=True) + if out.exit_code != 0: + raise Exception(out.stderr) + else: + data['log'] = out.stdout elif task.compute == 'demoremote': @@ -772,33 +799,39 @@ def containers(request): # Do we have to operate on a specific container? if uuid: + try: - # Get the task (raises if none available including no permission) - container = Container.objects.get(uuid=uuid) + # Get the container (raises if none available including no permission) + try: + container = Container.objects.get(uuid=uuid) + except Container.DoesNotExist: + raise ErrorMessage('Container does not exists or no access rights') + if container.user and container.user != request.user: + raise ErrorMessage('Container does not exists or no access rights') data['container'] = container + #------------------- + # Container actions + #------------------- + if action and action=='delete': # Delete container.delete() - # Unset container to load the list again - data['container'] = None - except Exception as e: data['error'] = 'Error in getting the container or performing the required action' logger.error('Error in getting the container with uuid="{}" or performing the required action: "{}"'.format(uuid, e)) return render(request, 'error.html', {'data': data}) - # Do we have to get he list of containers? - if not uuid: - - # Get containers configured on the platform, both private to this user and public - data['user_containers'] = Container.objects.filter(user=request.user) - data['platform_containers'] = Container.objects.filter(user=None) + #---------------- + # Container list + #---------------- - logger.debug(data) + # Get containers configured on the platform, both private to this user and public + data['user_containers'] = Container.objects.filter(user=request.user) + data['platform_containers'] = Container.objects.filter(user=None) return render(request, 'containers.html', {'data': data}) @@ -827,14 +860,18 @@ def add_container(request): if not container_type: raise ErrorMessage('No container type given') if not container_type in SUPPORTED_CONTAINER_TYPES: - raise ErrorMessage('No valid container type') + raise ErrorMessage('No valid container type, got "{}"'.format(container_type)) # Container registry container_registry = request.POST.get('container_registry', None) if not container_registry: raise ErrorMessage('No registry type given') if not container_registry in SUPPORTED_REGISTRIES: - raise ErrorMessage('No valid registry') + raise ErrorMessage('No valid container registry, got "{}"'.format(container_registry)) + + # Check container type vs container registry compatibility + if container_type+':'+container_registry in UNSUPPORTED_TYPES_VS_REGISTRIES: + raise ErrorMessage('Sorry, container type "{}" is not compatible with registry type "{}"'.format(container_type, container_registry)) # Container service ports container_service_ports = request.POST.get('container_service_ports', None)