diff options
-rw-r--r-- | ogcp/forms/action_forms.py | 5 | ||||
-rw-r--r-- | ogcp/templates/actions/repo_set.html | 69 | ||||
-rw-r--r-- | ogcp/templates/commands.html | 2 | ||||
-rw-r--r-- | ogcp/views.py | 62 |
4 files changed, 137 insertions, 1 deletions
diff --git a/ogcp/forms/action_forms.py b/ogcp/forms/action_forms.py index b4dfe7b..49c9f60 100644 --- a/ogcp/forms/action_forms.py +++ b/ogcp/forms/action_forms.py @@ -189,6 +189,11 @@ class OgliveForm(FlaskForm): oglive = SelectField(label=_l('ogLive')) ok = SubmitField(label=_l('Submit')) +class SetRepoForm(FlaskForm): + ips = HiddenField() + repo = SelectField(label=_l('Repository')) + ok = SubmitField(label=_l('Submit')) + class ImageCreateForm(FlaskForm): ip = HiddenField() os = SelectField(label=_l('Partition'), choices=[]) diff --git a/ogcp/templates/actions/repo_set.html b/ogcp/templates/actions/repo_set.html new file mode 100644 index 0000000..bdd7abf --- /dev/null +++ b/ogcp/templates/actions/repo_set.html @@ -0,0 +1,69 @@ +{% extends 'commands.html' %} +{% import "bootstrap/wtf.html" as wtf %} +{% import "macros.html" as macros %} + +{% set sidebar_state = 'disabled' %} +{% set btn_back = true %} + +{% block nav_setup %} active{% endblock %} +{% block content %} + +{% set ip_list = form.ips.data.split(' ') %} +{% set ip_count = ip_list | length %} +<h2 class="mx-5 subhead-heading"> + {{ _('Changing repository of %(ip_count)d computer(s)', ip_count=ip_count) }} +</h2> + +{{ macros.cmd_selected_clients(selected_clients) }} + +{% if repos_set|length > 1 %} +<div class="mx-5 form-group"> + <p>Selected clients have different ogLive</p> + + <table class="table table-hover"> + <thead class="thead-light"> + <tr> + <th>Repository</th> + <th>Clients</th> + </tr> + </thead> + <tbody class="text-left"> + {% for repo, clients in repos_set.items() %} + <tr> + <th>{{repo}}</th> + <td> + {% for ip in clients %}<div class="card d-inline-block" style="padding: 5px; margin: 3px;">{{ ip }}</div>{% endfor %} + </td> + </tr> + {% endfor %} + </tbody> + </table> +</div> +{% endif %} + +{{ wtf.quick_form(form, + action=url_for('action_repo_set'), + method='post', + button_map={'ok': 'primary'}, + extra_classes="m-5") }} + + +<!-- jQuery --> +<script src="{{ url_for('static', filename='AdminLTE/plugins/jquery/jquery.min.js') }}"></script> +<script> + var reposSet = {{ repos_set|tojson|safe }}; + // Update pill data + $('.badge-pill').each(function(index) { + for (const repo in reposSet) { + for (const clientName of reposSet[repo]) { + if ($(this).html().includes(clientName)) { + $(this).html($(this).html() + '<br>' + repo); + break; + } + } + } + }); +</script> + + +{% endblock %} diff --git a/ogcp/templates/commands.html b/ogcp/templates/commands.html index 48630ea..41a0917 100644 --- a/ogcp/templates/commands.html +++ b/ogcp/templates/commands.html @@ -40,6 +40,8 @@ <div class="dropdown-menu" aria-labelledby="dropdownMenuButton"> <input class="btn btn-light dropdown-item{% block nav_setup_set_bootmode %}{% endblock %}" type="submit" value="{{ _('Set boot mode') }}" form="scopesForm" formaction="{{ url_for('action_mode') }}" formmethod="get"> + <input class="btn btn-light dropdown-item{% block nav_setup_set_repo %}{% endblock %}" type="submit" value="{{ _('Set repository') }}" + form="scopesForm" formaction="{{ url_for('action_repo_set') }}" formmethod="get"> <input class="btn btn-light dropdown-item{% block nav_setup_set_oglive %}{% endblock %}" type="submit" value="{{ _('Set ogLive') }}" form="scopesForm" formaction="{{ url_for('action_oglive') }}" formmethod="get"> <input class="btn btn-light dropdown-item{% block nav_setup_setup %}{% endblock %}" type="submit" value="{{ _('Partition & Format') }}" diff --git a/ogcp/views.py b/ogcp/views.py index 77bad42..c24cb73 100644 --- a/ogcp/views.py +++ b/ogcp/views.py @@ -15,7 +15,7 @@ from ogcp.forms.action_forms import ( GenericForm, SelectClientForm, ImageUpdateForm, ImportClientsForm, ServerForm, DeleteRepositoryForm, RepoForm, FolderForm, CacheForm, ClientMoveForm, RunScriptForm, ImageConfigForm, ImageFetchForm, - ServerConfigurationForm + ServerConfigurationForm, SetRepoForm ) from flask_login import ( current_user, LoginManager, @@ -2416,6 +2416,66 @@ def action_oglive(): selected_clients=selected_clients) +def get_clients_repo_dictionary(ips, server, repositories): + repos = {} + repo_id_to_name = {repo["id"]: repo["name"] for repo in repositories} + + for ip in ips: + r = server.get('/client/info', payload={"client": [ip]}) + if not r: + raise ServerError + if r.status_code != requests.codes.ok: + raise ServerErrorCode + resp = r.json() + repo_name = repo_id_to_name[resp['repo_id']] + if repo_name not in repos: + repos[repo_name] = [ip] + else: + repos[repo_name].append(ip) + return repos + +@app.route('/action/repo/set', methods=['GET', 'POST']) +@login_required +def action_repo_set(): + form = SetRepoForm(request.form) + if request.method == 'POST': + ips = form.ips.data.split(' ') + payload = {'clients': ips, 'id': int(form.repo.data)} + server = get_server_from_clients(ips) + r = server.post('/client/repo', payload) + if not r: + return ogserver_down('commands') + if r.status_code == requests.codes.ok: + flash(_('Repo set ogLive request sent successfully'), + category='info') + else: + flash(_('Ogserver replied with status code not ok'), + category='error') + return redirect(url_for('commands')) + + else: + ips = parse_elements(request.args.to_dict()) + form.ips.data = " ".join(ips) + if not validate_elements(ips): + return redirect(url_for('commands')) + + server = get_server_from_clients(list(ips)) + try: + repositories = get_repositories(server) + repos_set = get_clients_repo_dictionary(ips, server, repositories) + except ServerError: + return ogserver_down('commands') + except ServerErrorCode: + return ogserver_error('commands') + + form.repo.choices = [(repo["id"], repo["name"]) for repo in repositories] + + scopes, clients = get_scopes(set(ips)) + selected_clients = list(get_selected_clients(scopes['scope']).items()) + return render_template('actions/repo_set.html', repos_set=repos_set, form=form, scopes=scopes, + selected_clients=selected_clients) + + @app.route('/action/image/create', methods=['GET', 'POST']) @login_required def action_image_create(): |