summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@open-infrastructure.net>2021-06-07 08:18:26 +0000
committerDaniel Baumann <daniel.baumann@open-infrastructure.net>2021-07-26 12:50:07 +0000
commitd316c8e8f42f66348bb08cf1ed58fc4d0cd4e722 (patch)
tree14ca491889a64564c9ebb94f01f7aaac43ab3185
parentAlso adding notifications in container main program. (diff)
downloadcompute-tools-tmp-web.tar.xz
compute-tools-tmp-web.zip
Adding webfrontend (WIP).tmp-web
Signed-off-by: Daniel Baumann <daniel.baumann@open-infrastructure.net>
-rw-r--r--share/web/TODO.txt10
-rwxr-xr-xshare/web/compute-tools.py159
-rw-r--r--share/web/footer.html.in9
-rw-r--r--share/web/header.html.in77
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 + '&amp;command=stop"><button type="button" class="btn btn-warning">stop</button></a> ' +
+ '</div> '+
+ '<a href="' + Url + '?name=' + name + '&amp;command=kill"><button type="button" class="btn btn-danger">kill</button></a> '
+ )
+ else:
+ print(
+ '<a href="' + Url + '?name=' + name + '&amp;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&amp;command=start"><button type="button" class="btn btn-success">start</button></a>
+ <a href="{Url}?name=ALL&amp;command=stop"><button type="button" class="btn btn-warning">stop</button></a>
+ </div>
+ <a href="{Url}?name=ALL&amp;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 />