executions.py 5.78 KB
Newer Older
1
# Copyright (c) 2017, Daniele Venzano
2 3 4 5 6 7 8 9 10 11 12 13 14 15
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.

16 17
"""Web pages and functions related to executions."""

18
import datetime
19
import json
20
import math
21 22 23
import time

from zoe_lib.config import get_conf
24

25
import zoe_api.exceptions
26
from zoe_api.web.request_handler import ZoeWebRequestHandler
27 28


29
class ExecutionStartWeb(ZoeWebRequestHandler):
30
    """Handler class"""
31

32 33
    def post(self):
        """Start an execution."""
34
        if self.current_user is None:
35
            return
36

37 38 39
        app_descr_json = self.request.files['file'][0]['body'].decode('utf-8')
        app_descr = json.loads(app_descr_json)
        exec_name = self.get_argument('exec_name')
40

41 42 43 44 45
        try:
            new_id = self.api_endpoint.execution_start(self.current_user, exec_name, app_descr)
        except zoe_api.exceptions.ZoeException as e:
            self.error_page(error_message=e.message)
            return
46

47
        self.redirect(self.reverse_url('execution_inspect', new_id))
48 49


50
class ExecutionListWeb(ZoeWebRequestHandler):
51
    """Handler class"""
52 53 54
    PAGINATION_ITEM_COUNT = 50

    def get(self, page=0):
55
        """Home page with authentication."""
56
        if self.current_user is None:
57
            return
58

59
        page = int(page)
60 61
        executions_count = self.api_endpoint.execution_count(self.current_user)
        executions = self.api_endpoint.execution_list(self.current_user, base=page*self.PAGINATION_ITEM_COUNT, limit=self.PAGINATION_ITEM_COUNT)
62 63

        template_vars = {
64
            "user": self.current_user,
65 66 67 68
            'executions': sorted(executions, key=lambda e: e.id, reverse=True),
            'current_page': page,
            'max_page': math.ceil(executions_count / self.PAGINATION_ITEM_COUNT),
            'last_page': len(executions) < self.PAGINATION_ITEM_COUNT
69
        }
Daniele Venzano's avatar
Daniele Venzano committed
70
        self.render('execution_list.jinja2', **template_vars)
71 72


73
class ExecutionRestartWeb(ZoeWebRequestHandler):
74
    """Handler class"""
75

76 77
    def get(self, execution_id: int):
        """Restart an already defined (and not running) execution."""
78
        if self.current_user is None:
79
            return
80

81 82 83 84 85 86
        try:
            e = self.api_endpoint.execution_by_id(self.current_user, execution_id)
            new_id = self.api_endpoint.execution_start(self.current_user, e.name, e.description)
        except zoe_api.exceptions.ZoeException as e:
            self.error_page(error_message=e.message)
            return
87

88
        self.redirect(self.reverse_url('execution_inspect', new_id))
89 90


91
class ExecutionTerminateWeb(ZoeWebRequestHandler):
92
    """Handler class"""
93

94 95
    def get(self, execution_id: int):
        """Terminate an execution."""
96
        if self.current_user is None:
97
            return
98

99
        try:
100
            self.api_endpoint.execution_terminate(self.current_user, execution_id, 'user {} request from web interface'.format(self.current_user.username))
101 102
        except zoe_api.exceptions.ZoeException as e:
            self.set_status(e.status_code, e.message)
103
            return
104

105
        self.redirect(self.reverse_url('home_user'))
106 107


108
class ExecutionInspectWeb(ZoeWebRequestHandler):
109
    """Handler class"""
110

111 112
    def get(self, execution_id):
        """Gather details about an execution."""
113
        if self.current_user is None:
114
            return
115

116 117
        try:
            e = self.api_endpoint.execution_by_id(self.current_user, execution_id)
118 119
        except zoe_api.exceptions.ZoeException as ex:
            self.set_status(ex.status_code, ex.message)
120
            return
121

122
        services_info, endpoints = self.api_endpoint.execution_endpoints(self.current_user, e)
123

124 125
        template_vars = {
            "e": e,
126
            "services_info": services_info,
127
            "endpoints": endpoints,
128
            'killed_at': e.time_submit + datetime.timedelta(hours=e.owner.quota.runtime_limit)
129
        }
130

131
        if get_conf().enable_plots and e.time_start is not None:
132
            grafana_url_template = 'https://cloud-platform.eurecom.fr/grafana/dashboard/db/zoe-executions?orgId=1&from={}&to={}&var-execution_id={}&refresh=1y'
133 134 135 136 137 138 139
            if e.time_end is None:
                e_time_end = int(time.time() * 1000)
            else:
                e_time_end = int((e.time_end - datetime.datetime(1970, 1, 1)) / datetime.timedelta(seconds=1) * 1000)
            e_time_start = int((e.time_start - datetime.datetime(1970, 1, 1)) / datetime.timedelta(seconds=1) * 1000)
            template_vars['grafana_url'] = grafana_url_template.format(e_time_start, e_time_end, execution_id)

Daniele Venzano's avatar
Daniele Venzano committed
140
        self.render('execution_inspect.jinja2', **template_vars)
141 142


143
class ServiceLogsWeb(ZoeWebRequestHandler):
144 145 146 147
    """Handler class"""

    def get(self, service_id):
        """Gather details about an execution."""
148
        if self.current_user is None:
149
            return
150

151 152 153 154 155
        try:
            service = self.api_endpoint.service_by_id(self.current_user, service_id)
        except zoe_api.exceptions.ZoeException as e:
            self.set_status(e.status_code, e.message)
            return
156 157 158

        template_vars = {
            "service": service,
159 160 161
            "log_path": "{}/{}/{}/{}.txt".format(get_conf().log_url, get_conf().deployment_name, service.execution_id, service.name),
            "websocket_base": get_conf().websocket_base + get_conf().reverse_proxy_path,
            'use_websockets': get_conf().log_use_websockets
162
        }
Daniele Venzano's avatar
Daniele Venzano committed
163
        self.render('service_logs.jinja2', **template_vars)