mirror of https://git.48k.eu/ogcp
ogcp: add view to assign repo to clients
Add /action/repo/set in Commands to assign a repository to multiple clients. The view includes the actual repo assigned in the client pills and shows a table with the clients grouped by repo when multiple repos are assigned among the selected clients.master
parent
a1b164b106
commit
6b33268b5c
|
@ -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=[])
|
||||
|
|
|
@ -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 %}
|
|
@ -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') }}"
|
||||
|
|
|
@ -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():
|
||||
|
|
Loading…
Reference in New Issue