diff options
author | Daniel Baumann <daniel.baumann@open-infrastructure.net> | 2021-06-07 08:18:26 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@open-infrastructure.net> | 2021-07-26 12:50:07 +0000 |
commit | d316c8e8f42f66348bb08cf1ed58fc4d0cd4e722 (patch) | |
tree | 14ca491889a64564c9ebb94f01f7aaac43ab3185 | |
parent | Also adding notifications in container main program. (diff) | |
download | compute-tools-d316c8e8f42f66348bb08cf1ed58fc4d0cd4e722.tar.xz compute-tools-d316c8e8f42f66348bb08cf1ed58fc4d0cd4e722.zip |
Adding webfrontend (WIP).tmp-web
Signed-off-by: Daniel Baumann <daniel.baumann@open-infrastructure.net>
-rw-r--r-- | share/web/TODO.txt | 10 | ||||
-rwxr-xr-x | share/web/compute-tools.py | 159 | ||||
-rw-r--r-- | share/web/footer.html.in | 9 | ||||
-rw-r--r-- | share/web/header.html.in | 77 |
4 files changed, 255 insertions, 0 deletions
diff --git a/share/web/TODO.txt b/share/web/TODO.txt new file mode 100644 index 0000000..7ef5e13 --- /dev/null +++ b/share/web/TODO.txt @@ -0,0 +1,10 @@ +TODO: + +- add actions to start/stop/terminal for all containers +- add commands for container-server too (like reboot, terminal, infos, debug-tools, etc.) +- add container-all commands +- show container log at the bottom in a text-area (logtail.js) +- put container-list output in a ajax refreshable area/box and refresh automatically every n minutes +- add manual refresh button +- add auto refresh toggle +- add 'drop-down' button to switch between 'cnt console' and 'cnt enter' diff --git a/share/web/compute-tools.py b/share/web/compute-tools.py new file mode 100755 index 0000000..defe543 --- /dev/null +++ b/share/web/compute-tools.py @@ -0,0 +1,159 @@ +#!/usr/bin/python3 + +# Copyright (C) 2014-2021 Daniel Baumann <daniel.baumann@open-infrastructure.net> +# +# SPDX-License-Identifier: GPL-3.0+ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from cgi import FieldStorage +from os import getenv +from subprocess import Popen, PIPE +from sys import exit + +def print_html(html_file): + with open(html_file, "r") as file: + html = file.read() + + Host = getenv("HTTP_HOST", "n/a") + Protocol = getenv("REQUEST_SCHEME", "n/a") + Script = getenv("SCRIPT_NAME", "n/a") + + Url = Protocol + '://' + Host + Script + + print(html.format(**locals())) + +def main(): + Host = getenv("HTTP_HOST", "n/a") + Protocol = getenv("REQUEST_SCHEME", "n/a") + Script = getenv("SCRIPT_NAME", "n/a") + User = getenv("REMOTE_USER", "n/a") + + Url = Protocol + '://' + Host + Script + + form = FieldStorage() + + if form.getvalue("command"): + Command = form.getvalue("command").split()[0] + + if Command == 'start' or Command == 'kill': + Options = '-f' + else: + Options = ' ' + + if "name" in form: + Name = form.getvalue("name").split()[0] + + if Command and Name: + command = 'env CONTAINER_USER="' + User + '" sudo --preserve-env=CONTAINER_USER cnt ' + Command + ' -n ' + Name + ' ' + Options + command_line = command.split() + cnt = Popen(command_line, stdout=PIPE) + + print('Location: ' + Url) + print + + print("Content-Type: text/html\n\n") + + print_html("header.html.in") + + command = 'env CONTAINER_USER="' + User + '" sudo --preserve-env=CONTAINER_USER cnt list -f sh' + command_line = command.split() + cnt_list = Popen(command_line, stdout=PIPE) + containers = cnt_list.stdout.readlines() + + print('<table class="table table-sm" style="width: 100%;">') + print('<thead class="thead-dark">') + print('<tr> <th>#</th> <th>System</th> <th>OS</th> <th>IP</th> <th>Actions</th> </tr>') + print('</thead>') + print('<tbody>') + + index = 0 + + for container in containers: + index = index + 1 + name = container.rstrip().decode('utf-8') + + command = 'env CONTAINER_USER="' + User + '" sudo --preserve-env=CONTAINER_USER cnt info -n ' + name + ' --status' + command_line = command.split() + cnt = Popen(command_line, stdout=PIPE) + status = str(cnt.stdout.readline().decode('utf-8').strip()) + + command = 'env CONTAINER_USER="' + User + '" sudo --preserve-env=CONTAINER_USER cnt info -n ' + name + ' --os' + command_line = command.split() + cnt = Popen(command_line, stdout=PIPE) + os = str(cnt.stdout.readline().decode('utf-8').strip()) + + command = 'env CONTAINER_USER="' + User + '" sudo --preserve-env=CONTAINER_USER cnt info -n ' + name + ' --ip' + command_line = command.split() + cnt = Popen(command_line, stdout=PIPE) + ip = str(cnt.stdout.readline().decode('utf-8').strip()) + + if status == 'started': + index_button = '<span class="badge bg-success">' + str(index) + '</span>' + elif status == 'stopped': + index_button = '<span class="badge bg-danger">' + str(index) + '</span>' + else: + index_button = '<span class="badge bg-info">' + str(index) + '</span>' + + # FIXME: maybe move out in favour of: cnt info -n foo --support + if os == 'Debian 11 (bullseye)' or os == 'Debian 10 (buster)': + os_button = '<span class="badge bg-success">' + os + '</span>' + elif os == 'Debian 9 (stretch)': + os_button = '<span class="badge bg-warning">' + os + '</span>' + elif os == 'Debian 8 (jessie)' or os == 'Debian 7 (wheezy)' or os == 'Debian 6 (squeeze)': + os_button = '<span class="badge bg-danger">' + os + '</span>' + else: + os_button = '<span class="badge bg-info">' + os + '</span>' + + if not ip: + ip = 'none' + + print( + '<tr> ' + + '<td>' + index_button + '</td> ' + + '<td>' + name + '</td> ' + + '<td>' + os_button + '</td> ' + + '<td>' + ip + '</td> ' + + '<td> ' + + '<div class="btn-group" role="group"> ' + ) + + if status == 'started': + print( + '<button type="button" class="btn btn-success" disabled>start</button> ' + + '<a href="' + Url + '?name=' + name + '&command=stop"><button type="button" class="btn btn-warning">stop</button></a> ' + + '</div> '+ + '<a href="' + Url + '?name=' + name + '&command=kill"><button type="button" class="btn btn-danger">kill</button></a> ' + ) + else: + print( + '<a href="' + Url + '?name=' + name + '&command=start"><button type="button" class="btn btn-success">start</button></a> ' + + '<button type="button" class="btn btn-warning" disabled>stop</button> ' + + '</div> '+ + '<button type="button" class="btn btn-danger" disabled>kill</button> ' + ) + + print( + '</td> ' + + '</tr>') + + print('</tbody>') + print('</table>') + + print_html("footer.html.in") + + exit(0) + +if __name__ == '__main__': + main() diff --git a/share/web/footer.html.in b/share/web/footer.html.in new file mode 100644 index 0000000..9c92d61 --- /dev/null +++ b/share/web/footer.html.in @@ -0,0 +1,9 @@ + </div> + </form> + +</main> + + <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-gtEjrD/SeCtmISkJkNUaaKMoLD0//ElJ19smozuHV6z3Iehds+3Ulb9Bn9Plx0x4" crossorigin="anonymous"></script> + + </body> +</html> diff --git a/share/web/header.html.in b/share/web/header.html.in new file mode 100644 index 0000000..b986c8e --- /dev/null +++ b/share/web/header.html.in @@ -0,0 +1,77 @@ +<!doctype html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="description" content=""> + <meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors"> + <meta name="generator" content="Sphinx"> + + <meta http-equiv="refresh" content="300; url={Url}"> + + <title>container-tools - {Host}</title> + + <link rel="canonical" href="https://open-infrastructure.net/software/compute-tools"> + + <!-- Bootstrap core CSS --> + <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous"> + <link href="navbar.css" rel="stylesheet"> + + <!-- Favicons --> + <link rel="apple-touch-icon" href="/docs/5.0/assets/img/favicons/apple-touch-icon.png" sizes="180x180"> + <link rel="icon" href="/docs/5.0/assets/img/favicons/favicon-32x32.png" sizes="32x32" type="image/png"> + <link rel="icon" href="/docs/5.0/assets/img/favicons/favicon-16x16.png" sizes="16x16" type="image/png"> + <link rel="manifest" href="/docs/5.0/assets/img/favicons/manifest.json"> + <link rel="mask-icon" href="/docs/5.0/assets/img/favicons/safari-pinned-tab.svg" color="#7952b3"> + <link rel="icon" href="/docs/5.0/assets/img/favicons/favicon.ico"> + <meta name="theme-color" content="#7952b3"> + + + <!-- Custom styles for this template --> + <link href="navbar-top-fixed.css" rel="stylesheet"> + </head> + <body> + +<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark"> + <div class="container-fluid"> + <a class="navbar-brand" href="#">compute-tools</a> + <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation"> + <span class="navbar-toggler-icon"></span> + </button> + <div class="collapse navbar-collapse" id="navbarCollapse"> + <ul class="navbar-nav me-auto mb-2 mb-md-0"> + <li class="nav-item"> + <a class="nav-link active" aria-current="page" href="#">Home</a> + </li> + <li class="nav-item"> + <a class="nav-link" href="#">Link</a> + </li> + <li class="nav-item"> + <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a> + </li> + </ul> + <form class="d-flex"> + <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"> + <button class="btn btn-outline-success" type="submit">Search</button> + </form> + </div> + </div> +</nav> + +<main class="container"> + + <form id="form"> + <div class="form-group"> + + <h2>{Host}</h2> + + <p>All containers:</p> + + <div class="btn-group" role="group"> + <a href="{Url}?name=ALL&command=start"><button type="button" class="btn btn-success">start</button></a> + <a href="{Url}?name=ALL&command=stop"><button type="button" class="btn btn-warning">stop</button></a> + </div> + <a href="{Url}?name=ALL&command=kill"><button type="button" class="btn btn-danger">kill</button></a> + <a href="http://{Host}:7681" target="_blank"><button type="button" class="btn btn-dark">shell</button></a> + + <br /><br /><br /> |